Any `.py`

file is a Python **module**.

A module serves as a collection of variables and functions that can be used by other modules.

Modules that are executed directly are also called **scripts**.

In [ ]:

```
%%file math_stuff.py
def add_three_numbers(a, b, c):
return a + b + c
def multiply_three_numbers(a, b, c):
return a * b * c
def average_three_numbers(a, b, c):
return a + b + c / 3
```

In [ ]:

```
%%file demo.py
from math_stuff import add_three_numbers, multiply_three_numbers
a = 7
b = 2
c = 3
print(add_three_numbers(a, b, c))
print(multiply_three_numbers(a, b, c))
```

In [ ]:

```
%%file another_demo.py
import math_stuff
a = 3
b = 6
c = 8
print(math_stuff.add_three_numbers(a, b, c))
print(math_stuff.multiply_three_numbers(a, b, c))
```

In [ ]:

```
! python demo.py
```

In [ ]:

```
! python another_demo.py
```

Both `demo.py`

and `another_demo.py`

use the functions defined in `math_stuff.py`

.

Often, modules that provide functions that are intended to be used by other scripts are called **libraries**.

**PyTest** is a library we can use to test our code.

In [ ]:

```
%%file test_math_stuff.py
from math_stuff import add_three_numbers, multiply_three_numbers, average_three_numbers
def test_add_three_numbers():
result = add_three_numbers(2, 3, 4)
assert result == 9
result = add_three_numbers(-1, 0, 2)
assert result == 1
def test_multiply_three_numbers():
result = multiply_three_numbers(2, 3, 4)
assert result == 24
result = multiply_three_numbers(1, 0, 2)
assert result == 0
def test_multiply_three_numbers_with_negatives():
assert multiply_three_numbers(-1, -2, -3) == -6
def test_average_three_numbers():
assert average_three_numbers(1, 2, 3) == 2
```

`test_math_stuff.py`

¶**NOTES**

When writing tests:

- The name of the file with the tests starts with
`test_`

- Typically the rest of the name corresponds to the module being tested
- So, the tests for
`math_stuff.py`

would be in a file named`test_math_stuff.py`

- The name of each test function starts with
`test_`

- The rest of the name typically corresponds to the function being tested
- So, the tests for
`add_three_numbers`

would be tested by a function named`test_add_three_numbers`

- You might also include something about the specific case being tested, e.g.
`test_multiply_three_numbers_with_negatives`

- Use
`assert`

to test whether something you have tested matches your expectations - PyCharm automatically identifies tests.
- Demonstrate how to run them
- Go over test outputs
- individual tests with output
- observe the failed test (
`average_three_numbers`

)

Our business-critical Python script isn't working correctly:

`important_business.py`

Write tests for the functions found in

`list_tools.py`

and fix the problem!

**NOTES**

- Run
`important_business.py`

. It fails. We need better test coverage! - Create a file named
`test_list_tools.py`

- Add tests for each function in
`list_tools.py`

`only_evens`

has a bug.- Test for all even numbers
- Test for all odd numbers
- Test for a mix of even and odds
- Test for
`0`

(should be treated as even)

`twice_as_long`

- test on lengths as well as contents
- test on a typical list
- test on an empty list

`sum_all`

- test on typical list
- test on empty list (should return
`0`

) - test on floats
- test on negatives

In [ ]:

```
%%file list_tools.py
def only_evens(items):
"""Return a list containing only the even elements of the input list"""
result = []
for item in items:
if item % 2 != 0:
result.append(item)
return result
def twice_as_long(items):
"""Return a list that is twice as long as the input: A, B, C => A, B, C, A, B, C"""
result = []
for item in items:
result.append(item)
for item in items:
result.append(item)
return result
def sum_all(numbers):
"""Sum all the numbers in a list"""
result = 0
for item in numbers:
result = result + item
return result
```

In [ ]:

```
%%file important_business.py
from list_tools import only_evens, twice_as_long, sum_all
numbers = [2, 0, 1, 3, 8, 4]
numbers = only_evens(numbers)
numbers = twice_as_long(numbers)
result = sum_all(numbers)
if result == 28:
print("Success! 😊")
else:
print("Fail. ☠️")
```

- Help us demonstrate that individual pieces of our code are working
- Help us quickly identify parts of our code that are not working
- Are most helpful when you write them as you go, instead of all at the very end
- Help us design good functions
- Write functions that have a clear, simple purpose that would be easy to test