{ "cells": [ { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "d318a69c0183d493dc01e862e2873199", "grade": false, "grade_id": "cell-e485a74242e7179c", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Worksheet 01b: Writing functions & tests\n", "\n", "## Getting Started\n", "\n", "Load the requirements for this worksheet:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "dcad541c1a8b922ccc27d249078abd86", "grade": false, "grade_id": "cell-a4468420bb3744af", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "suppressPackageStartupMessages(library(palmerpenguins))\n", "suppressPackageStartupMessages(library(lubridate))\n", "suppressPackageStartupMessages(library(tidyverse))\n", "suppressPackageStartupMessages(library(testthat))\n", "suppressPackageStartupMessages(library(dplyr))\n", "suppressPackageStartupMessages(library(gapminder))\n", "suppressPackageStartupMessages(library(digest))" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "ea8fd55508fed592395a0bbe0082b804", "grade": false, "grade_id": "cell-61ef8fcf920036ba", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "The following code chunk has been unlocked, to give you the flexibility to start this document with some of your own code. Remember, it's bad manners to keep a call to `install.packages()` in your source code, so don't forget to delete these lines if you ever need to run them." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# An unlocked code cell." ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "ead7b991d3c4bf44bf66551806a70433", "grade": false, "grade_id": "cell-bcacce63d5eb75b0", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 1\n", "\n", "Create a function that allows you to compute the max minus min of the Adelie penguins body mass. A code snippet to calculate max minus min *without a function* is shown to help you - essentially, your task is to turn this code snippet into a function. Be sure to make all three objects shown below.\n", "\n", "```r\n", "# put into practice your knowledge of dplyr to subset the penguins dataset to only those from the Adelie species\n", "adelie <- penguins %>% \n", " filter(FILL_THIS_IN == FILL_THIS_IN) %>% \n", " drop_na()\n", "\n", "# write your function here\n", "max_minus_min <- function (x) FILL_THIS_IN - FILL_THIS_IN\n", "\n", "# apply your function to the Adelie penguins body mass\n", "answer1.0 <- max_minus_min(FILL_THIS_IN)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "2b8df34e28903792af3018977fae6fd0", "grade": false, "grade_id": "cell-87603a76f3c2d5f9", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "head(adelie)\n", "cat(\"Your final answer:\")\n", "answer1.0" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "1fb36535e38c48506a5de8f884ab66d1", "grade": true, "grade_id": "cell-76deea33a2374b6f", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 1\", {\n", " expect_known_hash(sort(round(adelie$body_mass_g, 2)), '4c17a7083ab7d3e61b770cfd1ea2515d')\n", " expect_known_hash(round(answer1.0, 3), '112052893c8bd4663fea8754262dfb9e')\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "d68aa953992315003f42127c5d977f7b", "grade": false, "grade_id": "cell-cb4a911466e26ceb", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2\n", "\n", "Test your function on the life expectancy variable of the `gapminder` dataset and assign the returned value to R object `answer2.0`. Does it work?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "aa2ea8cb0f0c07b3b0f24020854482fe", "grade": false, "grade_id": "cell-f5b58ab34c202448", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "786d732e42365f3e5cfd59ac0b9054a4", "grade": true, "grade_id": "cell-bce7628c22c0193f", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2\", {\n", " expect_known_hash(round(answer2.0, 3), '4ca07c689295be575d7b41d1c7d8c61f')\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "3c6a422d81b8fdd0140adbf1ae10fa17", "grade": false, "grade_id": "cell-b8a402fb6bb3f999", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 3\n", "\n", "The function shouldn't work with all inputs, such as the following examples:\n", "\n", "```\n", "max_minus_min(adelie)\n", "max_minus_min(penguins$species)\n", "max_minus_min(\"stat545 is great\")\n", "```\n", "\n", "We expect errors for these, because it wouldn't make sense to compute the max minus min in any of those arguments. \n", "\n", "However, R will often try and make sense of your function... and that is not always a good thing. If you run the code below, you will see that the function is giving us an output for arguments that do not make any sense." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "5db53ba48dc7d8c256f32919a87fe4f5", "grade": false, "grade_id": "cell-163c191696c36e5f", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "max_minus_min(gapminder[c('lifeExp', 'gdpPercap', 'pop')])\n", "max_minus_min(c(TRUE, FALSE, TRUE))" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "3e32181c255d808b7a3975271ccf1ddd", "grade": false, "grade_id": "cell-630d1c2f6690c65e", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "To avoid this from happening, rewrite the `max_minus_min` function to include a `stopifnot()`. Think of what should be the argument of `stopifnot()` to solve this issue - in other words, what should be the object class that the function `max_minus_min` should accept (e.g. a dataframe, a character, a number...)?\n", "\n", "```r\n", "answer3.0 <- function(x) {\n", " stopifnot(FILL_THIS_IN) \n", " max(x) - min(x)\n", "}\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "5a599054f27ef267bbfdcf3033cd41ac", "grade": false, "grade_id": "cell-dd463f2745b2f285", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "answer3.0" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "3be442c05f2eef31aff8fea8d8baf66e", "grade": true, "grade_id": "cell-c4f721c6b2b4cb91", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 3\", {\n", " expect_known_hash(mode(answer3.0), 'ecce171f95c8c2466c6516b40beca466')\n", " expect_known_hash(length(formals(answer3.0)), '4b5630ee914e848e8d07221556b0a2fb')\n", " expect_error(answer3.0('a'), 'is.numeric')\n", " expect_error(answer3.0(c(TRUE, FALSE)), 'is.numeric')\n", " expect_error(answer3.0(list(1:5)), 'is.numeric')\n", " expect_known_hash(answer3.0(1:5), '234a2a5581872457b9fe1187d1616b13')\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "8892e2d5e18d938cf17694975d719abe", "grade": false, "grade_id": "cell-d083a08f5ad1cc6e", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 4\n", "\n", "In the following chunk, I created a function to convert fahrenheit to celsius. When I test it with arguments that theoretically shouldn't give an output, it appears to have the same problem as our original `max_minus_min()` function." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "3b27d88a04e1254fcf747de7fd4b9a30", "grade": false, "grade_id": "cell-b101dbc844542503", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "# here I write the function\n", "fahrenheit_to_celsius <- function(temp_F) {\n", " (temp_F - 32) * 5 / 9\n", "}" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "757ab31240f8b684db7c8cee81ee7e48", "grade": false, "grade_id": "cell-6ba3a71b7e8416aa", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "# here I test it on something that theoretically should not work.. but does\n", "fahrenheit_to_celsius(c(TRUE, FALSE, FALSE, TRUE))" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "b3582e3e0a105870e093ac0280f161a6", "grade": false, "grade_id": "cell-92b59ed8a017de13", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Rewrite the `fahrenheit_to_celsius` function using `if()` and `stop()` instead of `stopifnot()`. This allows you to write your own (more informative) error message.\n", "\n", "*Hint:* Remember that you are trying to stop the function from working **if the argument is not numeric.**\n", "\n", "```r\n", "answer4.0 <- function(temp_F) {\n", " if(!FILL_THIS_IN(FILL_THIS_IN)) {\n", " stop('I am so sorry, but this function only works for numeric input!\\n',\n", " 'You have provided an object of class: ', class(FILL_THIS_IN)[1])\n", " }\n", " temp_C <- (temp_F - 32) * 5 / 9\n", " return(FILL_THIS_IN)\n", "}\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "96525dd30c69ab812b70394e151fbb68", "grade": false, "grade_id": "cell-a9fd920afd588b68", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "3d6771c73327b4194a82742827da5c1b", "grade": true, "grade_id": "cell-bd7e981ed966e789", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 4\", {\n", " expect_known_hash(mode(answer4.0), 'ecce171f95c8c2466c6516b40beca466')\n", " expect_known_hash(length(formals(answer4.0)), '4b5630ee914e848e8d07221556b0a2fb')\n", " expect_error(answer4.0(c('4', '20', '12')))\n", " expect_error(answer4.0(c(TRUE, FALSE)))\n", " expect_error(answer4.0(list(1:5)))\n", " expect_known_hash(answer4.0(c(350, 425, 550)), 'ebd71f9f1506f215d50b4d64546b8f7e')\n", " expect_known_hash(answer4.0(1:5), '1faaa13b49412d6a48b0d25c0011f38f')\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "c097fb95d73b43836c2ab3cac728d2a9", "grade": false, "grade_id": "cell-ae8804db6997b30d", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 5\n", "\n", "Write a function that takes 2 arguments (name them `x` and `y`), raises the first argument to the power of the second one, and outputs a string with a message that indicates what the output of the function is. Use `stopifnot()` so that the function *only* takes numeric arguments." ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "d49d06446a317948123a30c17347f233", "grade": false, "grade_id": "cell-9cd9dead5f850e93", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "```r\n", "# function to write text output of x raised to the power y.\n", "answer5.0 <- function(FILL_THIS_IN, FILL_THIS_IN) {\n", " stopifnot(FILL_THIS_IN && FILL_THIS_IN)\n", " result <- FILL_THIS_IN\n", " paste(FILL_THIS_IN, \"raised to the power\", FILL_THIS_IN, \"is\", FILL_THIS_IN)\n", "}\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "5b3c1e749d07c6af7d1649fa5a003591", "grade": false, "grade_id": "cell-cccfed813998b291", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "answer5.0(3, 4)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "7e1ee4f901cf7c58d6fec35d6cac8ba6", "grade": true, "grade_id": "cell-d812b59d2daad9c2", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 5\", {\n", " expect_known_hash(mode(answer5.0), 'ecce171f95c8c2466c6516b40beca466')\n", " expect_known_hash(length(formals(answer5.0)), 'c01f179e4b57ab8bd9de309e6d576c48')\n", " expect_error(answer5.0(3, c('4', '20', '12')), 'is.numeric')\n", " expect_error(answer5.0(c(TRUE, FALSE), 2), 'is.numeric')\n", " expect_error(answer5.0(list(1:5), 1:3), 'is.numeric')\n", " expect_equal(answer5.0(1/5, 4), '0.2 raised to the power 4 is 0.0016')\n", " expect_known_hash(answer5.0(2, 2:5), \"b6c31695e3646007c2364b462147e44b\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "cc74320130479be8b34f1aa98fd5e9d5", "grade": false, "grade_id": "cell-7005bc21c9703ebd", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 6\n", "\n", "Use `expect_equal()` to check that manually calculating the max minus min of the bill length of all penguins in the `penguins` dataset yields the same result as using a function.\n", "\n", "Run the following chunk of code first." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "eecc89b71ee8f9b15dd617306475dfe7", "grade": false, "grade_id": "cell-383f8acc4706a9b9", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "x <- max(penguins$bill_length_mm, na.rm = TRUE) \n", "y <- min(penguins$bill_length_mm, na.rm = TRUE) \n", "x - y" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "c7ab0f49ce98067e567345ec17e68dcb", "grade": false, "grade_id": "cell-b37d00bcab16b017", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "I have written a slightly tweaked version of the `max_minus_min()` function created in **Q1** that allows the user to control the behaviours around NAs. This is important - without removing NAs, if you try running `max_minus_min()` with `penguins$bill_length_mm` as an argument, the output will be NA." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "b3dd4729e9a10d0fd0625096cc481ca5", "grade": false, "grade_id": "cell-eaf5b985bb719eb9", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "# new function\n", "max_minus_min2 <- function(x, na.rm = TRUE) {\n", " if(!is.numeric(x)) {\n", " stop('I am so sorry, but this function only works for numeric input!\\n',\n", " 'You have provided an object of class: ', class(x)[1])\n", " }\n", " max(x, na.rm = na.rm) - min(x, na.rm = na.rm)\n", "}" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "71ad2c7bd9b4dbb887baf8377dd29852", "grade": false, "grade_id": "cell-cbf1064e3c65e120", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Now, check that the output of this function when calculating the max minus min of the bill length across all penguins in the `penguins` dataset is the same as calculating it \"manually\" as we did above - in other words, that the function output **equals** 27.5.\n", "\n", "__NOTE__: We're _only_ getting you to store the output of `expect_equal()` in variable `answer6.0` so that we can run the autograder! Otherwise, you'd only ever run it on its own, without assigning it to anything.\n", "\n", "_Psst... take a look at the test cells in these worksheets. Notice a similarity?_\n", "\n", "```r\n", "answer6.0 <- expect_equal(FILL_THIS_IN, FILL_THIS_IN(FILL_THIS_IN$FILL_THIS_IN, na.rm = TRUE))\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "2cbb571ec512286d0159a41d3e25267a", "grade": false, "grade_id": "cell-e175cc0e06687492", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "answer6.0" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "0fcdfa9add7a236f7e9a07fd7f783176", "grade": true, "grade_id": "cell-852745acab813c93", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 6\", {\n", " expect_known_hash(answer6.0, 'b342fe04b00f00610a95dd8ebcc5967c')\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "7b4a2e40d11577c61b7231af316d1de8", "grade": false, "grade_id": "cell-c9eb8afbacc927c2", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "There are other `expect_` functions such as `expect_identical()`, `expect_match()` or `expect_output()` that you can look into further [here](https://r-pkgs.org/tests.html#test-structure). " ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "1232e4565f61c25d3e3ffd75a6992278", "grade": false, "grade_id": "cell-de5e8aafd7ed7bbd", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 7\n", "\n", "Let's try combining a different expectation function and `test_that()` with a very easy example. We start by writing a very simple function that returns the string \"Hello world, my name is\" + your name." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "8e2ab05b729787c122ed185bd7e49b88", "grade": false, "grade_id": "cell-e1471a691fd2d1bb", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "hello_world <- function(x) {\n", " stopifnot(is.character(x)) # we want x to be a character\n", " paste('Hello world, my name is', x)\n", "}" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "5588fad9619b8c97f25bd1e0eb3e8445", "grade": false, "grade_id": "cell-4b9a5ac3822d15a8", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "In the next code cell, we'll run `hello_world()` with \"Julie Payette\" as an argument, just to see the output!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "446711188810651063ff8f10e8278e76", "grade": false, "grade_id": "cell-59d7decdaf647c97", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "hello_world(\"Julie Payette\")" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "cbf2ff1ffa8245dbb09e0371bbac03e2", "grade": false, "grade_id": "cell-5f61dc5783562620", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Great! Now, let's simply test that the output of `hello_world()` with _your_ name as an argument matches the character vector **'Hello world, my name is'**. I have added an example of how `expect_match()` works to help you write your test.\n", "\n", "```\n", "eggplants <- \"Eggplants are purple\"\n", "expect_match(eggplants, \"Eggplants\") # works\n", "expect_match(eggplants, \"purple\") # works\n", "\n", "# your turn\n", "answer7.0 <- test_that(\"returns hello world + your name string\", {\n", " expect_match(FILL_THIS_IN(FILL_THIS_IN), FILL_THIS_IN)\n", "})\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "c68a159a8355f3224fbda4522a0ec4c3", "grade": false, "grade_id": "cell-b539fd87839f379e", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "49ddd10d28f80e50581d27b5c2af5a28", "grade": true, "grade_id": "cell-eed9a46d9c5ae258", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 7\", {\n", " expect_known_hash(answer7.0, 'bb73ad91bcb7e948250d465016f7b')\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "857dbc8d84ee5c1d881c3a4830b7c9aa", "grade": false, "grade_id": "cell-95fbf3199a22b139", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 8\n", "\n", "Create a function called `m` that multiplies two numbers (arguments `x` and `y`). Create a test for function `m` with description \"Testing multiplication function\" and add a few scenarios to it:\n", "\n", "+ Check if `m(2,3)` equals `6`\n", "+ Check if `m(2, c(2,3))` equals `c(4,6)`\n", "+ Check if `m(2, \"3\")` throws an error \"non-numeric argument to binary operator\"\n", "\n", "```r\n", "m <- function(FILL_THIS_IN) FILL_THIS_IN\n", "answer8.0 <- test_that(\"Testing multiplication function\", {\n", " expect_equal(FILL_THIS_IN)\n", " expect_equal(FILL_THIS_IN)\n", " expect_error(FILL_THIS_IN, FILL_THIS_IN)\n", "})\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "cca1904eab99340a3a7a3de1c71bee0d", "grade": false, "grade_id": "cell-df60f586bfdb80b7", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "0e113112eb3ab7c0c5f6b36cd2caf57b", "grade": true, "grade_id": "cell-64b58cd50bfda83c", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 8\", {\n", " expect_known_hash(round(answer8.0, 2), '6717f2823d3202449301145073ab8')\n", "})" ] } ], "metadata": { "kernelspec": { "display_name": "R", "language": "R", "name": "ir" }, "language_info": { "codemirror_mode": "r", "file_extension": ".r", "mimetype": "text/x-r-source", "name": "R", "pygments_lexer": "r", "version": "4.3.1" } }, "nbformat": 4, "nbformat_minor": 4 }