Slide 1

Slide 1 text

TESTING IN PYTHON A PRIMER

Slide 2

Slide 2 text

OVERVIEW • Vocabulary • unittest (the module) • pytest • mock

Slide 3

Slide 3 text

VOCABULARY

Slide 4

Slide 4 text

UNIT TEST VOCABULARY • A unit test exercises a unit of work (or code) • Unit tests should be small and thus fast (100s of tests in a couple seconds fast) • Unit tests should ignore collaborators • Unit tests should test one bit of behavior • Units of code should be well factored and will make unit testing easier

Slide 5

Slide 5 text

INTEGRATION VOCABULARY • Tests that work with collaborators • For example: • If class A uses an instance of class B, class B is the collaborator • If class A talks to example.com, example.com is the collaborator • If a unit of code opens a file, that file is the collaborator • Disclaimer: We will not discuss integration testing here

Slide 6

Slide 6 text

INDEPENDENCE VOCABULARY • Each test should not rely on state created by another test • Tests should be able to be run in any order and still pass • Tests should be runnable in isolation

Slide 7

Slide 7 text

TEST PARAMETRIZATION/PARAMETERIZATION VOCABULARY • Yes, you can spell parameterization as parametrization. Yes, it trips me up very often • This allows you to have many different inputs to a test function so you can write fewer lines of code but have more tests. If you have a test function with N items parametrizing it, you will have N tests appear in your test run. 1 for each set of parameters.

Slide 8

Slide 8 text

FIXTURES VOCABULARY • Fixtures are constant bits of data used in tests • Fixtures can also be reusable bits of code (especially when your code is data)

Slide 9

Slide 9 text

COVERAGE VOCABULARY • Test coverage measures what lines of code and branches in your code are exercised by your tests • Many projects aim for 100% test coverage • Test coverage is a lie but still very useful to have

Slide 10

Slide 10 text

TEST DRIVEN DEVELOPMENT VOCABULARY • Also known as “TDD” • Refers to the practice of writing a test before writing the code that the test exercises • If you are adding a new method to a class, you write the test for that method first, then write the method and run the tests to see if the method satisfies the test you wrote

Slide 11

Slide 11 text

HOW MANY IS TOO MANY?

Slide 12

Slide 12 text

EXAMPLE CODE

Slide 13

Slide 13 text

def file_iterator(filename): with open(filename) as fd: for line in fd: yield line.strip()

Slide 14

Slide 14 text

TESTING TOOLS

Slide 15

Slide 15 text

UNITTEST TESTING TOOLS • Benefits: • Standard library • Excellent test collection • Familiarity for most people inside and out of Python (xUnit style)

Slide 16

Slide 16 text

UNITTEST TESTING TOOLS • Disadvantages: • Everything in a class • Tests must be an actual module • Different between versions of Python

Slide 17

Slide 17 text

UNITTEST - EXAMPLE TESTING TOOLS from unittest import TestCase class TestExample(TestCase): def test_strips_newlines(self): for line in file_iterator( ‘example.py’): self.assertFalse( line.endswith(‘\n’))

Slide 18

Slide 18 text

UNITTEST - EXAMPLE TESTING TOOLS def test_strips_leading_ws(self): “””Verify we strip leading whitespace.””” for line in file_iterator( ‘example.py’): self.assertFalse( line.startswith(‘ ’))

Slide 19

Slide 19 text

UNITTEST TESTING TOOLS • Assertions - self.assert* • assertEqual/assertNotEqual • assertTrue/assertFalse/assertIs/assertIsNot • assertIsNone/assertIsNotNone • assertIn/assertNotIn • assertIsInstance/assertNotIsInstance • and more - https://docs.python.org/3/library/unittest.html? highlight=unittest.testcase#unittest.TestCase

Slide 20

Slide 20 text

UNITTEST - EXAMPLE TESTING TOOLS def assertNotEndswith(self, line, text): self.assertFalse(line.endswith( text)) # in our test self.assertNotEndswith(line, ‘\n’)

Slide 21

Slide 21 text

PYTEST TESTING TOOLS • Benefits: • Mature, well maintained, frequently updated • Beautiful test output + tonnes of plugins • Does not require classes (tests can be plain functions) • Uses assert statement, supports parametrization, has test fixtures • Works perfectly with unittest

Slide 22

Slide 22 text

PYTEST TESTING TOOLS • Disadvantages: • Not in the standard library • python -m pip install pytest • Has some very sharp very narrow and very bizarre corner cases
 (not going to go into these now or in questions)

Slide 23

Slide 23 text

UNITTEST - REFRESHER TESTING TOOLS from unittest import TestCase class TestExample(TestCase): def test_strips_newlines(self): for line in file_iterator( ‘example.py’): self.assertFalse( line.endswith(‘\n’))

Slide 24

Slide 24 text

PYTEST - ASSERT EXAMPLE TESTING TOOLS def test_strips_newlines(): for line in file_iterator( ‘example.py’): assert (line.endswith(‘\n’) is False)

Slide 25

Slide 25 text

PYTEST - PARAMETRIZATION EXAMPLE TESTING TOOLS import pytest @pytest.mark.parametrize(‘file’, [ ‘example.py’, ‘example2.py’]) def test_strips_newlines(file): for line in file_iterator(file): assert (line.endswith(‘\n’)) is False)

Slide 26

Slide 26 text

PYTEST - FIXTURE EXAMPLE TESTING TOOLS import pytest @pytest.fixture def file_iter(): return file_iterator(‘ex.py’) def test_strips_nl(file_iter): for line in file_iter: assert (line.endswith(‘\n’)) is False)

Slide 27

Slide 27 text

MOCK TESTING TOOLS • Benefits: • Mature, well maintained, frequently updated • Helps excise pesky collaborators • So valuable it was added to the standard library in Python 3.4 • Actually lives as unittest.mock in Python 3.4+ • Can patch out objects, functions, etc. • Works with unittest, pytest, whatever

Slide 28

Slide 28 text

PYTEST TESTING TOOLS • Disadvantages: • Not in the standard library before Python 3.4 • python -m pip install mock • Some people find it very confusing

Slide 29

Slide 29 text

MOCK - EXAMPLE TESTING TOOLS from mock import Mock, patch def test_strips_nl(file_iter): file = Mock() file.__iter__.return_value = [ ‘0\n’, ‘1\n’] with patch(‘open’) as mockopen: mockopen.return_value = file assert list(file_iter) == [ ‘0’, ‘1’]

Slide 30

Slide 30 text

MOCK - EXAMPLE TESTING TOOLS from mock import Mock, patch def test_strips_nl(file_iter): # … snip … mockopen.assert_called_once_with( ‘ex.py’) assert (file.__iter__.called is True)

Slide 31

Slide 31 text

MOCK - ADDENDUM TESTING TOOLS • There are times to not use mock: • When you’re talking over a network and trying to fake out data

Slide 32

Slide 32 text

THANK YOU