Functions: Assertions and Testing
Write a Function…
- call it join_three_strings
- it should take three arguments: a, b, c
- it should return a single string composed of a, b, and c separated by a space
- handle non-string arguments (see last example)
Example Usage:
Let's write this function together →
Join Three Strings Solution
Syntax
A quick summary on syntax:
Parameters
What are the values of a, b and c in the above function when called as below:→
- a = 'one', b = 'two', c = 'three'
- a = 'three', b = 'one', c = 'two'
- a = 'three', b = 'two', c = 'one'
Parameters Summary
- parameters
- variable names used within a function
- reference the values passed in as arguments
- parameters are positional; order determines what names match to what variables
- def f(p1, p2, p3):
- p1 will refer to the first value passed in
- p2 to the second
- etc.
Return Values
What's the difference between these two definitions of our function? What gets printed out for each code sample? →
Version #1
Version #2
Return Values Continued
The first definition (#1) returns a string, while the other (#2) doesn't return a value.
Printing out the results of both functions gives:
- Version #1
one two three
- (this function returns a string, and the caller prints)
- Version #2
one two three
None
- (this function prints out the string itself, and then returns no value, or
None
)
The Return Statement
- a function can return a value after it is called
- this is done by using the return statement
- the return statement immediately stops the execution of a function
- …and returns the value that follows it
- the value can be any value! (return True)
- it can even be an expression (return 1 + 1)
- if a function doesn't explicitly return a value, it gives back None, a special value that means the absence of a value
Defining vs Calling
What gets printed out for each version of code?
1: nothing, 2: nothing, 3: one two three
Testing Programs / Functions
So far, we've tested our programs by: →
- printing things out to the screen
- manually inspecting the output
- …for every test case that we have
Some shortcomings of manual testing →
- it's tedious!
- it's error prone!
What can we do to make testing less tedious and error prone? →
Assertions for Testing
Let's get the computer to test it for us! Assertions are a way to systematically check the state of our program.
- we can test expected values against the actual values by using an assert statement
- the assert statement will stop program execution if if a specified condition is not True
- for testing, that condition is expected value == actual value
Assertions as "Sanity Checks"
- note that assertions are not limited to this type of testing
- they're usually used to check for conditions that shouldn't happen
- such as the return value of a function not being an expected type
- or the parameters of a function adhering to certain bounds
Assert Syntax
- the keyword assert
- followed by any condition - an expression that returns True or False (usually expected == observed)
- followed by a comma
- followed by a string that represents the test
An Assertion Example
Let's use assertions to test an incorrect implementation of our function - one that doesn't have spaces between the strings. →
An Assertion Example That Actually Passes
Let's fix the program… and see what happens. →
Another Assertion Example
Let's use assertions to test an incorrect implementation of an absolute_value function →
Questions About Assertions
- why use assertions
- to test specific portions of your program
- to cut down on manual testing
- they're almost like inline documentation for your functions
- why use assertions over if statements
- you can actually turn off assertions when you run your program
- more concise than if statements
- specifically meant for checking the internal state of your program
Documentation
- what if someone else is reading your code, but your code is kind of complex?
- what if you forgot what your code does!?
- you can write comments to give you a hint
- or you can write docstrings that will show up in Python's documentation tools
Docstrings
- we can document our functions using a docstring
- it's a string that immediately follows the head of a function definition
- it's in triple quotes
- it describes the function
In later classes, we'll see where this string shows up, but for now just use it as inline documentation for your code.