{"assignment":{"_schema_version":2,"course_id":37,"date_created":"2022-06-28T19:00:00+00:00","date_modified":"2025-08-17T17:48:46.644188+00:00","extra_instructor_files":"","extra_starting_files":"","forked_id":null,"forked_version":null,"hidden":false,"id":988,"instructions":"## Unit Tests\n\n* Find problems earlier.\n* Make it easier to change things later.\n* Have more confidence in gluing together code.\n\nOnce you've created a function, how do you know if it is correct? You could carefully read over the function, but you might miss something.\nInstead, programmers use collections of _unit_ _tests_ to determine if their code works as expected.\nUnit testing is an important professional practice to help you: \nfind problems early, facilitate changes down the road, and make \nit easier to glue together pieces of code.\nUnit tests are not magic, however.\nThey cannot tell you that a program is definitely correct.\nThey can only tell you if a program is definitely not correct.\n\n## Example Unit Test\n\n```python feet_to_inches\n# Import unit test function from testing module\nfrom bakery import assert_equal\n\n# Function definition\ndef feet_to_inches(distance: int)->int:\n    return distance * 12\n\n# Actual unit test\nassert_equal(feet_to_inches(2), 24)\n```\n\nA unit test calls a function with a known input and compares the result to a known output.\nFor example, consider this function that converts feet to inches.\nAbove the function call is a special statement that imports \u2014 or makes available \u2014 the `assert_equal` function from the test module.\nWe use this function on the line below to write our unit test.\nWe call `feet_to_inches` and pass in `2` and assert that we expect a result of `24`.\n\n## Code Coverage\n\n```python\nfrom bakery import assert_equal\n\ndef feet_to_inches(distance:int) ->int:\n    return distance * 12\n\nassert_equal(feet_to_inches(2), 24)\nassert_equal(feet_to_inches(.5), 6.0)\nassert_equal(feet_to_inches(0), 0)\nassert_equal(feet_to_inches(-4), -48)\nassert_equal(feet_to_inches(10000), 120000)\n```\n\nWhen you write many unit tests, you increase the coverage of your code.\nCoverage is usually measured by the number of lines of code that are executed, divided by the number of lines of code you've written.\nRight now, if you write any unit tests, you'll be able to get good code coverage.\nSoon, we will see that you will need to write more unit tests to handle loops and conditionals.\nBut for now, avoid having uncovered code by writing unit tests for each function.\n\n## Representative Cases\n\n| Case | Input | -> | Output |\n|------|-------|--------|-----------|\n| Positive integer | 1 | -> | 12 |\n| Positive float | .5 | -> | 6.0 |\n| Zero | 0 | -> | 0 |\n| Negative number | -4 | -> | -48 |\n| Large positive number | 10000 | -> | 120000 |\n\nA tricky part of making unit tests is thinking of appropriate test cases.\nThe goal is to cover many possible scenarios while writing the minimum number of cases.\nIn our conversion function before, we tried it with a small positive number, a decimal number, a negative number, a large number, and zero.\nThese are all representative cases.\nDepending on what our function is doing, you might need more or fewer test cases.\n\n## Representative Cases for Strings\n\n* letters,\n* digits,\n* symbols,\n* whitespace characters,\n* Strings combining the above,\n* The empty string\n\nRepresentative cases vary by the type of the input.\nThe Boolean type only has two possible values, so you should usually test both a `True` and a `False` value to get full coverage.\nBut if you are working with strings, you instead have to think about letters, digits, symbols, and whitespace characters.\nConsider not only strings that are ONLY these characters, but also mixtures of these characters, in varying amounts, like a mixture of only letters and digits.\nYou also always want to think about the special case of the empty string, which often breaks string handling programs.\n\n## Failing Unit Tests\n\n* Function: `inches_to_feet`\n* Given input: `1`\n* Expected output: `12`\n* Actual output: `-5`\n* `12 != 5`, you have an error in your calculation!\n\nWhen a unit test fails, it reports the actual and expected values so that the programmer can then debug their program.\nIf you only try a function with one output, you might think that the function is correct.\nBut until you run unit tests, you shouldn't believe that.\nOf course, unit tests are not conclusive either; they are merely evidence to support the hypothesis that your code is correct.\n\n## Passing Unit Tests\n\n![Example of a failing instructor unit test in BlockPy, including the terms \"Instructor Feedback\" and \"Incorrect Answer\".](functions_testing_blockpy_failed_test.png)\n\nThe larger your program, the more important it is to unit test individual pieces.\nHowever, unit tests are also helpful as you learn the basics.\nEvery program you write in this course will be unit tested, which means that we will try running your program against many inputs and outputs.\nSometimes you will be asked to write your own unit tests, and sometimes we will run our own unit tests on your code.\nJust because your program appears to give the right output, you must pass all the unit tests!\n\n## Judging Unit Tests\n\n```python valid-thorough\nfrom bakery import assert_equal\n\n# Incorrect version!\ndef add(left: int, right: int) -> int:\n    return left + 4\n  \n# Valid tests show the correct behavior\nassert_equal(add(1, 4), 5)\nassert_equal(add(3, 4), 7)\n# Thorough tests expose the incorrect version's failure\nassert_equal(add(4, 3), 7)\nassert_equal(add(5, 5), 10)\n```\n\nYour collection of unit tests needs to be valid and thorough:\nA collection is _valid_ if the assertions pass for all possible correct implementations of the program.\nA collection is _thorough_ if the assertions fail for any possible incorrect implementations.\n\nAlthough it is impossible to consider every possible way to write a program, you should spend some time thinking about alternatives to your solution.\nIt can be very difficult to think of test cases that break your program, but doing so is critical to writing good tests!\n\n## Testing Before Defining\n\n![The steps of defining a function: read the problem, define the header, write a docstring, write some example tests, write the body, and write more tests.](functions_testing_design_recipe.png)\n\nMany computer scientists recommend writing tests BEFORE you write the body of the function.\nThis forces you to think about the problem you are working on and what the expected result should be.\nIf you cannot write unit tests for the function, then you likely do not understand the problem well enough to write the body.\nOften, writing out the tests will help you realize what the body of the functions should do.\nSometimes this means you must do the complex math or other operations of the body yourself, which can be tiresome \u2014 but again, can often help you understand how the body is supposed to work.\n\n## Function Design Recipe\n\n1. Read the problem\n2. Define the header\n3. Write a docstring\n4. Write some example tests\n5. Write the body\n6. Write more tests\n\nThe previous diagram lays out the steps usually recommended in the process of defining a function.\nThis model is sometimes called the \"design recipe\" for defining functions.\nHere are the steps in a bit more depth:\n\n**Read the problem**: Look over the description of the function to identify the function's name, parameters, and expected return type. Make sure you understand what the function is supposed to do.\n\n**Define the header:** Write the first line of the function using the `def` keyword.\n\n**Write a docstring:** We will talk more about this in a future lesson, but the next step is to create the body of the function with a triple-quoted string that explains what the function is supposed to do. Alternatively, instead of this documentation, sometimes you might just write the word `pass` so you have something in place.\n\n**Write some example tests:** Before you write the body properly, most experts suggest writing a few example tests first. To reiterate, this helps you understand what the function is supposed to do. But don't exhaust yourself writing all the tests you need; focus on just writing a few examples to guide your thinking.\n\n**Write the body:** Now you can sit down and write the body of the function. This can be one of the hardest and most complicated steps with the most variety. However, the earlier steps can help you solve this step.\n\n**Write more tests:** After your function's body is written, you should write more tests to increase your confidence that the function works.\n\nOften, writing tests is easier when you have already written the body since you can think of more concrete examples related to the code.\nStill, writing tests before the body often forces you to think more deeply about the problem without getting bogged down with implementation details.\n\n## Summary\n\n- Tests are used to diagnose whether a function is working correctly.\n- Good tests can make it easier to debug your program and have confidence that a function is working correctly.\n- The code coverage metric tells you how much of your code has been executed compared to how many lines of code are in your program. Failing to test functions means that they will be uncovered.\n- A unit test matches an input with an expected output for a given function call.\n- When a unit test is executed, the actual output is compared to the expected output. If they do not match, we say the unit test has failed. If they do match, we say the unit test has passed.\n- Many functions have common possible inputs that you should test for, such as the empty string or the integer zero.\n- Often, writing some example tests before you write the body of the function will help you better understand the problem you are trying to solve.\n- Developers should create a collection of unit tests demonstrating validity and thoroughness:\n  - Validity: All unit tests should pass for correct programs.\n  - Thoroughness: At least one unit test should fail for incorrect programs.\n\n","ip_ranges":"","name":"2A5) Testing Functions Reading","on_change":"","on_eval":"","on_run":"","owner_id":1,"owner_id__email":"acbart@udel.edu","points":0,"public":true,"reviewed":false,"sample_submissions":[],"settings":"{\n  \"header\": \"Testing Functions\",\n  \"slides\": \"bakery_functions_testing.pdf\",\n  \"youtube\": {\n    \"Bart\": \"UpTDCz65m-g\",\n    \"Amy\": \"CAWv16m-zXs\"\n  },\n  \"video\": {\n    \"Bart\": \"https://blockpy.cis.udel.edu/videos/bakery_functions_testing-Bart.mp4\",\n    \"Amy\": \"https://blockpy.cis.udel.edu/videos/bakery_functions_testing-Amy.mp4\"\n  },\n  \"summary\": \"In this lesson, you will learn functions are evaluated for correctness using Unit Tests. Unit tests are a battery of known inputs and outputs for a function that can be run conveniently to verify assertions about the program.\",\n  \"small_layout\": true\n}","starting_code":"","subordinate":true,"tags":[],"type":"reading","url":"bakery_functions_testing_read","version":7},"ip":"216.73.216.157","submission":{"_schema_version":3,"assignment_id":988,"assignment_version":7,"attempts":0,"code":"","correct":false,"course_id":37,"date_created":"2026-05-20T14:01:52.553993+00:00","date_due":"","date_graded":"","date_locked":"","date_modified":"2026-05-20T14:01:52.553993+00:00","date_started":"","date_submitted":"","endpoint":"","extra_files":"","feedback":"","grading_status":"NotReady","id":2036926,"score":0.0,"submission_status":"Started","time_limit":"","url":"submission_url-8ef81df8-6f34-4d5d-aafd-4ed05f08f2b9","user_id":2044668,"user_id__email":"","version":0},"success":true}
