0% found this document useful (0 votes)
81 views

Beginners Python Cheat Sheet PCC Testing

The document discusses testing functions and classes in Python using the pytest library. It provides examples of writing passing and failing tests for a function that returns a full name, and modifying the function code to fix the failing test.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
81 views

Beginners Python Cheat Sheet PCC Testing

The document discusses testing functions and classes in Python using the pytest library. It provides examples of writing passing and failing tests for a function that returns a full name, and modifying the function code to fix the failing test.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 2

Beginner's Python

Installing pytest A failing test (cont.)


Installing pytest with pip Running the test
When you change your code, it’s important to run your existing

Cheat Sheet -
$ python -m pip install --user pytest
tests. This will tell you whether the changes you made affect existing
behavior.
Testing a function (cont.) $ pytest

Testing Your Code Building a testcase with one unit test


To build a test case, import the function you want to test. Any
functions that begin with test_ will be run by pytest. Save this file
============= test session starts =============
test_full_names_failing.py F [100%]

as test_full_names.py. ================== FAILURES ===================


Why test your code? from full_names import get_full_name _______________ test_first_last _______________
> full_name = get_full_name('janis',
When you write a function or a class, you can also 'joplin')
write tests for that code. Testing proves that your code def test_first_last():
"""Test names like Janis Joplin.""" E TypeError: get_full_name() missing 1
works as it's supposed to in the situations it's designed full_name = get_full_name('janis', required positional argument: 'last'
to handle, and also when people use your programs in 'joplin')
unexpected ways. Writing tests gives you confidence assert full_name == 'Janis Joplin' =========== short test summary info ===========
that your code will work correctly as more people FAILED test_full_names.py::test_first_last...
Running the test
begin to use your programs. You can also add new ============== 1 failed in 0.04s ==============
Issuing the pytest command tells pytest to run any file beginning
features to your programs and know whether or not with test_. pytest reports on each test in the test case.
you've broken existing behavior by running your tests. The dot after test_full_names.py represents a single passing test. Fixing the code
A unit test verifies that one specific aspect of your pytest informs us that it ran 1 test in about 0.01 seconds, and that When a test fails, the code needs to be modified until the test
the test passed. passes again. Don’t make the mistake of rewriting your tests to fit
code works as it's supposed to. A test case is a your new code, otherwise your code will break for anyone who's
collection of unit tests which verify that your code's $ pytest using it the same way it's being used in the failing test.
behavior is correct in a wide variety of situations. ============= test session starts ============= Here we can make the middle name optional:
The output in some sections has been trimmed for platform darwin -- Python 3.11.0, pytest-7.1.2
rootdir: /.../testing_your_code def get_full_name(first, last, middle=''):
space. collected 1 item """Return a full name."""

Testing a function: a passing test test_full_names.py . [100%] if middle:


The pytest library provides tools for testing your code. To ============== 1 passed in 0.01s ============== full_name = f"{first} {middle} {last}"
try it out, we’ll create a function that returns a full name. We’ll else:
full_name = f"{first} {last}"
use the function in a regular program, and then build a test Testing a function: A failing test
case for the function.
Failing tests are important; they tell you that a change in the return full_name.title()
A function to test code has affected existing behavior. When a test fails, you
Save this as full_names.py need to modify the code so the existing behavior still works. Running the test
Now the test should pass again, which means our original
def get_full_name(first, last): Modifying the function functionality is still intact.
"""Return a full name.""" We’ll modify get_full_name() so it handles middle names, but
$ pytest
we’ll do it in a way that breaks existing behavior.
full_name = f"{first} {last}" ============= test session starts =============
return full_name.title() def get_full_name(first, middle, last): test_full_names.py . [100%]
"""Return a full name."""
Using the function full_name = f"{first} {middle} {last}" ============== 1 passed in 0.01s ==============
Save this as names.py return full_name.title()
from full_names import get_full_name Using the function

janis = get_full_name('janis', 'joplin')


print(janis)
from full_names import get_full_name
Python Crash Course
john = get_full_name('john', 'lee', 'hooker') A Hands-on, Project-Based
print(john) Introduction to Programming
bob = get_full_name('bob', 'dylan')
print(bob) ehmatthes.github.io/pcc_3e
david = get_full_name('david', 'lee', 'roth')
print(david)
Adding new tests Testing a class Using fixtures
You can add as many unit tests to a test case as you need. Testing a class is similar to testing a function, since you’ll A fixture is a resource that's used in multiple tests. When the
To write a new test, add a new function to your test file. If the mostly be testing its methods. name of a fixture function is used as an argument to a test
file grows too long, you can add as many files as you need. function, the return value of the fixture is passed to the test
A class to test
function.
Testing middle names Save as account.py
When testing a class, you often have to make an instance
We’ve shown that get_full_name() works for first and last names.
class Account(): of the class. Fixtures let you work with just one instance.
Let’s test that it works for middle names as well.
"""Manage a bank account."""
from full_names import get_full_name Using fixtures to support multiple tests
def __init__(self, balance=0): The instance acc can be used in each new test.
def test_first_last(): """Set the initial balance.""" import pytest
"""Test names like Janis Joplin.""" self.balance = balance from account import Account
full_name = get_full_name('janis',
'joplin') def deposit(self, amount): @pytest.fixture
assert full_name == 'Janis Joplin' """Add to the balance.""" def account():
self.balance += amount account = Account()
def test_middle(): return account
"""Test names like David Lee Roth.""" def withdraw(self, amount):
full_name = get_full_name('david', """Subtract from the balance.""" def test_initial_balance(account):
'roth', 'lee') self.balance -= amount """Default balance should be 0."""
assert full_name == 'David Lee Roth' assert account.balance == 0
Building a testcase
Running the tests For the first test, we’ll make sure we can start out with different initial
def test_deposit(account):
The two dots after test_full_names.py represent two passing tests. balances. Save this as test_accountant.py.
"""Test a single deposit."""
$ pytest from account import Account account.deposit(100)
============= test session starts ============= assert account.balance == 100
collected 2 items def test_initial_balance():
test_full_names.py .. [100%] """Default balance should be 0.""" def test_withdrawal(account):
account = Account() """Test a deposit followed by withdrawal."""
============== 2 passed in 0.01s ============== assert account.balance == 0 account.deposit(1_000)
account.withdraw(100)
def test_deposit(): assert account.balance == 900
A variety of assert statements """Test a single deposit."""
You can use assert statements in a variety of ways, to account = Account() Running the tests
check for the exact conditions you want to verify. account.deposit(100) $ pytest
Verify that a==b, or a != b assert account.balance == 100 ============= test session starts =============
collected 3 items
assert a == b Running the test
test_account.py ... [100%]
assert a != b $ pytest
Verify that x is True, or x is False ============= test session starts ============= ============== 3 passed in 0.01s ==============
collected 2 items
assert x test_account.py .. [100%]
assert not x pytest flags
============== 2 passed in 0.01s ============== pytest has some flags that can help you run your tests
Verify an item is in a list, or not in a list efficiently, even as the number of tests in your project grows.
assert my_item in my_list When is it okay to modify tests? Stop at the first failing test
assert my_item not in my_list
In general you shouldn’t modify a test once it’s written. When $ pytest -x
a test fails it usually means new code you’ve written has
Running tests from one file broken existing functionality, and you need to modify the new Only run tests that failed during the last test run
In a growing test suite, you can have multiple test files. code until all existing tests pass. $ pytest --last-failed
Sometimes you'll only want to run the tests from one file. If your original requirements have changed, it may be
You can pass the name of a file, and pytest will only run the appropriate to modify some tests. This usually happens in
tests in that file: the early stages of a project when desired behavior is still Weekly posts about all things Python
$ pytest test_names_function.py being sorted out, and no one is using your code yet. mostlypython.substack.com

You might also like