SlideShare a Scribd company logo
1 of 49
Download to read offline
PyCon Korea 2019
pytest로 파이썬 코드 테스트하기
최영선
yeongseon.choe@gmail.com
PyCon Korea 2019
pytest
• Modify Code with Confidence
• Identify Bugs Early
• Improve System Design
https://alysivji.github.io/testing-101-introduction-to-testing.html#benefits-of-
testing
Why we should test code?
• python test framework.
• Advantages of pytest
• Easy to use
• Can run a specific test or subset of tests
• Skip tests
• Can run tests in parallel
What is pytest?
• Examples
• https://github.com/pallets/flask
What is pytest?
PyCon Korea 2019
1. Getting Started
• Requirements
• Python 3
• virtualenv
• Installation
Getting Started
$ virtualenv –p python3.7 venv
$ source virtualenv/bin/activate
$ (venv)
• An example of simple test
• Execution
# content of test_sample.py
def inc(x):
return x + 1
def test_answer():
assert int(3) == 5
$ pytest test_sample.py
• (venv) py.test test_sample.py
• (venv) py.test tests/test_sample.py
• (venv) py.test tests/
How to run test cases?
$ pytest -h
usage: pytest [options] [file_or_dir] [file_or_dir] [...]
positional arguments:
file_or_dir
Practice
# calculator.py
def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y
def divide(x, y):
return x / y
# calculator.py
def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y
def divide(x, y):
return x / y
# test_calculator.py
import pytest
from calculator import add, divide
def test_add():
assert add(1, 2) == 3
assert not add (2, 2) == 3
def test_divide():
with pytest.raises(ZeroDivisionError):
divide(1, 0)
PyCon Korea 2019
2. Project Structure
Structure of the Repository
• Run test
project/
sample/
__init__.py
sample.py
tests/
test_sample.py
$ cd project
$ python –m pytest tests/test_sample.py
Practice
$ cd pytest_tutorial
$ ls
calculator.py
test_calculator.py
$ cd pytest_tutorial
$ mkdir src
$ mkdir tests
$ mv caclculator.py src
$ mv test_calculator.py tests
$ pytest
# edit code
$ python –m pytest tests
PyCon Korea 2019
3. Fixture
Test Fixture
• A software test fixture sets up the system for the testing process by
providing it with all the necessary code to initialize it, thereby satisfying
whatever preconditions there may be.
• Frequently fixtures are created by handling setUp() and tearDown() events of
the unit testing framework.
Four phases of a test:
1. Set-up
2. Exercise, interacting with the system under test
3. Verify, determining whether the expected outcome has been
obtained
4. Tear down, to return to the original state
• Fixtures are run pytest before the actual test functions.
• @pytest.fixture() decorator
• Purpose
• Setup and Teardown for the tests (e.g, database)
• Test set for the tests
pytest fixtures
Practice
# calculator.py
class Calculator(object):
"""Calculator class"""
def __init__(self):
pass
@staticmethod
def add(a, b):
return a + b
@staticmethod
def subtract(a, b):
return a - b
@staticmethod
def multiply(a, b):
return a * b
@staticmethod
def divide(a, b):
return a / b
# calculator.py
class Calculator(object):
"""Calculator class"""
def __init__(self):
pass
@staticmethod
def add(a, b):
return a + b
@staticmethod
def subtract(a, b):
return a - b
@staticmethod
def multiply(a, b):
return a * b
@staticmethod
def divide(a, b):
return a / b
# test_calculator.py
from src.calculator import add
def test_add():
assert add(1, 2) == 3
# calculator.py
class Calculator(object):
"""Calculator class"""
def __init__(self):
pass
@staticmethod
def add(a, b):
return a + b
@staticmethod
def subtract(a, b):
return a - b
@staticmethod
def multiply(a, b):
return a * b
@staticmethod
def divide(a, b):
return a / b
# test_calculator.py
from src.calculator import Calculator
def test_add():
calculator = Calculator()
assert calculator.add(1, 2) == 3
assert calculator.add(2, 2) == 4
def test_subtract():
calculator = Calculator()
assert calculator.subtract(5, 1) == 4
assert calculator.subtract(3, 2) == 1
def test_multiply():
calculator = Calculator()
assert calculator.multiply(2, 2) == 4
assert calculator.multiply(5, 6) == 30
def test_divide():
calculator = Calculator()
assert calculator.divide(8, 2) == 4
assert calculator.divide(9, 3) == 3
# test_calculator.py
from src.calculator import Calculator
def test_add():
calculator = Calculator()
assert calculator.add(1, 2) == 3
assert calculator.add(2, 2) == 4
def test_subtract():
calculator = Calculator()
assert calculator.subtract(5, 1) == 4
assert calculator.subtract(3, 2) == 1
def test_multiply():
calculator = Calculator()
assert calculator.multiply(2, 2) == 4
assert calculator.multiply(5, 6) == 30
def test_divide():
calculator = Calculator()
assert calculator.divide(8, 2) == 4
assert calculator.divide(9, 3) == 3
# test_calculator.py
from src.calculator import Calculator
@pytest.fixture
def calculator():
calculator = Calculator()
return calculator
def test_add(calculator):
assert calculator.add(1, 2) == 3
assert calculator.add(2, 2) == 4
def test_subtract(calculator):
assert calculator.subtract(5, 1) == 4
assert calculator.subtract(3, 2) == 1
def test_multiply(calculator):
assert calculator.multiply(2, 2) == 4
assert calculator.multiply(5, 6) == 30
# confest.py
import pytest
from src.calculator import
Calculator
@pytest.fixture
def calculator():
calculator = Calculator()
return calculator
# test_calculator.py
from src.calculator import Calculator
@pytest.fixture
def calculator():
calculator = Calculator()
return calculator
def test_add(calculator):
assert calculator.add(1, 2) == 3
assert calculator.add(2, 2) == 4
def test_add_fail(calculator):
assert calculator.add(1, 2) != 6
assert calculator.add(2, 2) != 5
def test_multiply(calculator):
assert calculator.multiply(2, 2) == 4
assert calculator.multiply(5, 6) == 30
# test_calculator.py
from src.calculator import Calculator
def test_add(calculator):
assert calculator.add(1, 2) == 3
assert calculator.add(2, 2) == 4
def test_add_fail(calculator):
assert calculator.add(1, 2) != 6
assert calculator.add(2, 2) != 5
PyCon Korea 2019
4. Parameterize
pytest parameterize
• Define multiple sets of arguments and fixtures at the test function or class.
• @pytest.mark.parametrize: parametrizing test functions
• The builtin pytest.mark.parametrize decorator
Practice
# test_calculator.py
from src.calculator import Calculator
def test_add(calculator):
assert calculator.add(1, 2) == 3
assert calculator.add(2, 2) == 4
assert calculator.add(2, 2) == 4
pytest.mark.parametrize(argnames, argvalues)
# test_calculator.py
from src.calculator import Calculator
def test_add(calculator):
assert calculator.add(1, 2) == 3
assert calculator.add(2, 2) == 4
assert calculator.add(9, 2) == 11
@pytest.mark.parametrize(
"a, b, expected",
[(1, 2, 3),
(2, 2, 4),
(2, 7, 11)])
def test_add_fail(calculator, a, b, expected):
assert calculator.add(a, b) != expected
# test_calculator.py
from src.calculator import Calculator
@pytest.mark.parametrize(
"a, b, expected",
[(1, 2, 6),
(2, 2, 5),
(2, 7, 2)])
def test_add_fail(calculator, a, b, expected):
assert calculator.add(a, b) != expected
@pytest.mark.xfail(rason="wrong result")
@pytest.mark.parametrize(
"a, b, expected",
[(1, 2, 6),
(2, 2, 5),
(2, 7, 2)])
def test_add_fail(calculator, a, b, expected):
assert calculator.add(a, b) == expected
• Buildin markers: skip, skipif and fail
• skip: enable you to skip tests you don’t want to run
• @pytest.mark.skip(reason=‘something’)
• @pytest.mark.skipif(condition, reason=‘something’)
• xfail: we are telling pytest to run a test function, but we expect it to fail.
• @pytest.mark.fail
# test_calculator.py
from src.calculator import Calculator
@pytest.mark.xfail(rason="wrong result")
@pytest.mark.parametrize(
"a, b, expected",
[(1, 2, 6),
(2, 2, 5),
(2, 7, 2)])
def test_add_fail(calculator, a, b, expected):
assert calculator.add(a, b) == expected
@pytest.mark.parametrize(
"a, b, expected",
[pytest.param(1, 2, 6, marks=pytest.mark.xfail),
pytest.param(2, 2, 5, marks=pytest.mark.xfail),
pytest.param(2, 7, 2, marks=pytest.mark.xfail)])
def test_add_fail(calculator, a, b, expected):
assert calculator.add(a, b) == expected
# test_calculator.py
from src.calculator import Calculator
@pytest.mark.parametrize(
"a, b, expected",
[(1, 2, 3),
(2, 2, 4),
(2, 7, 9),
pytest.param(1, 2, 6, marks=pytest.mark.xfail),
pytest.param(2, 2, 5, marks=pytest.mark.xfail),
pytest.param(2, 7, 2, marks=pytest.mark.xfail)])
def test_add(calculator, a, b, expected):
assert calculator.add(a, b) == expected
# test_calculator.py
from src.calculator import Calculator
add_test_data = [
(1, 2, 3),
(2, 2, 4),
(2, 7, 9),
pytest.param(1, 2, 6, marks=pytest.mark.xfail),
pytest.param(2, 2, 5, marks=pytest.mark.xfail),
pytest.param(2, 7, 2, marks=pytest.mark.xfail)
]
@pytest.mark.parametrize(
"a, b, expected", add_test_data)
def test_add(calculator, a, b, expected):
assert calculator.add(a, b) == expected
• ids: optional parameter to parameterize()
• @pytest.mark.parameterize() decorator
• pytest.param(<value>, id=“something”)
# test_calculator.py
from src.calculator import Calculator
add_test_data = [
(1, 2, 3),
(2, 2, 4),
(2, 7, 9),
pytest.param(1, 2, 6, marks=pytest.mark.xfail),
pytest.param(2, 2, 5, marks=pytest.mark.xfail),
pytest.param(2, 7, 2, marks=pytest.mark.xfail)]
@pytest.mark.parametrize(
"a, b, expected", add_test_data, ids=[
"1 add 2 is 3",
"2 add 2 is 4",
"2 add 7 is 9",
"1 add 2 is not 6",
"2 add 2 is not 5",
"2 add 7 is not 2"] )
def test_add(calculator, a, b, expected):
assert calculator.add(a, b) == expected
# test_calculator.py
from src.calculator import Calculator
add_test_data = [
(1, 2, 3),
(2, 2, 4),
(2, 7, 9),
pytest.param(1, 2, 6, marks=pytest.mark.xfail),
pytest.param(2, 2, 5, marks=pytest.mark.xfail),
pytest.param(2, 7, 2, marks=pytest.mark.xfail)]
@pytest.mark.parametrize(
"a, b, expected", add_test_data, ids=[
"1 add 2 is 3",
"2 add 2 is 4",
"2 add 7 is 9",
"1 add 2 is not 6",
"2 add 2 is not 5",
"2 add 7 is not 2"] )
def test_add(calculator, a, b, expected):
assert calculator.add(a, b) == expected
# test_calculator.py
from src.calculator import Calculator
subtract_test_data = [
pytest.param(5, 1, 4, id="5 subtract 1 is 4"),
pytest.param(3, 2, 1, id="3 subtract 2 is 1"),
pytest.param(10, 2, 8, id="10 subtract 2 is 8"),
pytest.param(5, 1, 6, marks=pytest.mark.xfail, id="5 subtract 1 is 6"),
pytest.param(3, 2, 2, marks=pytest.mark.xfail, id="3 subtract 2 is 2"),
pytest.param(10, 2, 1, marks=pytest.mark.xfail, id="10 subtract 2 is 1")
]
@pytest.mark.parametrize(
"a, b, expected", subtract_test_data
)
def test_subtract(calculator, a, b, expected):
assert calculator.subtract(a, b) == expected
PyCon Korea 2019
5. Mock
• Thirty-party pytest plugin
• pytest-mock
• Swapping out part of the system to isolate bits of code
• Mock objects: test doubles, spies, fakes, or stubs..
• mock.patch
• mock.patch.object
pytest mock
Practice
• Installation
$ (venv) pip install pytest-mock
def test_add_with_mocker1(mocker, calculator):
"""Test functionality of add."""
mocker.patch.object(calculator, 'add', return_value=5)
assert calculator.add(1, 2) is 5
assert calculator.add(2, 2) is 5
def test_add_with_mocker2(mocker, calculator):
"""Test functionality of add."""
mocker.patch.object(calculator, 'add', side_effect=[1, 2])
assert calculator.add(1, 2) is 1
assert calculator.add(2, 2) is 2
def test_add_with_mocker3(mocker, calculator):
"""Test functionality of add."""
mocker.patch.object(calculator, 'add', side_effect=ZeroDivisionError())
with pytest.raises(ZeroDivisionError):
calculator.add(1, 2)
# calculator.py
import logging
logging.basicConfig(level=logging.INFO)
class Calculator():
"""Calculator class"""
def __init__(self):
self.logger = logging.getLogger(self.__class__.__name__)
def add(self, a, b):
self.logger.info(
"add {a} to {b} is {result}".format(
a=a, b=b, result=a + b
))
return a + b
@pytest.mark.parametrize(
"a, b, expected", add_test_data
)
# mocker: The mocker fixture is provided by the pytest-mock plugin
def test_add_spy_logger(mocker, calculator, a, b, expected):
spy_info = mocker.spy(calculator.logger, "info")
assert calculator.add(a, b) == expected
assert spy_info.called
assert spy_info.call_count == 1
calls = [mocker.call("add {a} to {b} is {expected}".format(
a=a, b=b, expected=expected
))]
assert spy_info.call_args_list == calls
References
• https://docs.pytest.org/en/latest/
• https://docs.python-guide.org/writing/structure/
• https://stackoverflow.com/questions/1896918/running-unittest-with-typical-
test-directory-structure
• https://www.slideshare.net/soasme/pytest
• https://github.com/pytest-dev/pytest-mock/

More Related Content

What's hot

[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기OKKY
 
Dr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterDr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterScott Wlaschin
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of CompositionScott Wlaschin
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Scott Wlaschin
 
Async programming and python
Async programming and pythonAsync programming and python
Async programming and pythonChetan Giridhar
 
The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsScott Wlaschin
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented ProgrammingScott Wlaschin
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)Scott Wlaschin
 
Python – Object Oriented Programming
Python – Object Oriented Programming Python – Object Oriented Programming
Python – Object Oriented Programming Raghunath A
 
Functional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioFunctional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioLuis Atencio
 
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's GuideEvolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's GuideVictor Rentea
 
Event Sourcing from the Trenches (with examples from .NET)
Event Sourcing from the Trenches (with examples from .NET)Event Sourcing from the Trenches (with examples from .NET)
Event Sourcing from the Trenches (with examples from .NET)Dennis Doomen
 
Inline Functions and Default arguments
Inline Functions and Default argumentsInline Functions and Default arguments
Inline Functions and Default argumentsNikhil Pandit
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Scott Wlaschin
 
Testing Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 worldTesting Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 worldYura Nosenko
 
뱅크샐러드 파이썬맛 레시피
뱅크샐러드 파이썬맛 레시피뱅크샐러드 파이썬맛 레시피
뱅크샐러드 파이썬맛 레시피겨울 정
 
Spring Framework - Expression Language
Spring Framework - Expression LanguageSpring Framework - Expression Language
Spring Framework - Expression LanguageDzmitry Naskou
 
Programmation orientée objet en PHP 5
Programmation orientée objet en PHP 5Programmation orientée objet en PHP 5
Programmation orientée objet en PHP 5Kristen Le Liboux
 

What's hot (20)

[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기
[OKKY 세미나] 정진욱 - 테스트하기 쉬운 코드로 개발하기
 
Dr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterDr Frankenfunctor and the Monadster
Dr Frankenfunctor and the Monadster
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of Composition
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)
 
Async programming and python
Async programming and pythonAsync programming and python
Async programming and python
 
The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of tests
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)
 
Python programming : Inheritance and polymorphism
Python programming : Inheritance and polymorphismPython programming : Inheritance and polymorphism
Python programming : Inheritance and polymorphism
 
Introduction to OOP(in java) BY Govind Singh
Introduction to OOP(in java)  BY Govind SinghIntroduction to OOP(in java)  BY Govind Singh
Introduction to OOP(in java) BY Govind Singh
 
Python – Object Oriented Programming
Python – Object Oriented Programming Python – Object Oriented Programming
Python – Object Oriented Programming
 
Functional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioFunctional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis Atencio
 
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's GuideEvolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
 
Event Sourcing from the Trenches (with examples from .NET)
Event Sourcing from the Trenches (with examples from .NET)Event Sourcing from the Trenches (with examples from .NET)
Event Sourcing from the Trenches (with examples from .NET)
 
Inline Functions and Default arguments
Inline Functions and Default argumentsInline Functions and Default arguments
Inline Functions and Default arguments
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013
 
Testing Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 worldTesting Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 world
 
뱅크샐러드 파이썬맛 레시피
뱅크샐러드 파이썬맛 레시피뱅크샐러드 파이썬맛 레시피
뱅크샐러드 파이썬맛 레시피
 
Spring Framework - Expression Language
Spring Framework - Expression LanguageSpring Framework - Expression Language
Spring Framework - Expression Language
 
Programmation orientée objet en PHP 5
Programmation orientée objet en PHP 5Programmation orientée objet en PHP 5
Programmation orientée objet en PHP 5
 

Similar to pytest로 파이썬 코드 테스트하기

Py.test
Py.testPy.test
Py.testsoasme
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My PatienceAdam Lowry
 
Effective testing with pytest
Effective testing with pytestEffective testing with pytest
Effective testing with pytestHector Canto
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test communityKerry Buckley
 
Python testing using mock and pytest
Python testing using mock and pytestPython testing using mock and pytest
Python testing using mock and pytestSuraj Deshmukh
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con djangoTomás Henríquez
 
Benchy, python framework for performance benchmarking of Python Scripts
Benchy, python framework for performance benchmarking  of Python ScriptsBenchy, python framework for performance benchmarking  of Python Scripts
Benchy, python framework for performance benchmarking of Python ScriptsMarcel Caraciolo
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и DjangoMoscowDjango
 
Unit Testing from Setup to Deployment
Unit Testing from Setup to DeploymentUnit Testing from Setup to Deployment
Unit Testing from Setup to DeploymentMark Niebergall
 
MT_01_unittest_python.pdf
MT_01_unittest_python.pdfMT_01_unittest_python.pdf
MT_01_unittest_python.pdfHans Jones
 
Running Intelligent Applications inside a Database: Deep Learning with Python...
Running Intelligent Applications inside a Database: Deep Learning with Python...Running Intelligent Applications inside a Database: Deep Learning with Python...
Running Intelligent Applications inside a Database: Deep Learning with Python...Miguel González-Fierro
 
Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023Mark Niebergall
 
關於測試,我說的其實是......
關於測試,我說的其實是......關於測試,我說的其實是......
關於測試,我說的其實是......hugo lu
 
Spock Testing Framework - The Next Generation
Spock Testing Framework - The Next GenerationSpock Testing Framework - The Next Generation
Spock Testing Framework - The Next GenerationBTI360
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Michelangelo van Dam
 
Mutation testing Bucharest Tech Week
Mutation testing Bucharest Tech WeekMutation testing Bucharest Tech Week
Mutation testing Bucharest Tech WeekPaco van Beckhoven
 

Similar to pytest로 파이썬 코드 테스트하기 (20)

Py.test
Py.testPy.test
Py.test
 
Auto testing!
Auto testing!Auto testing!
Auto testing!
 
How to fake_properly
How to fake_properlyHow to fake_properly
How to fake_properly
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My Patience
 
Effective testing with pytest
Effective testing with pytestEffective testing with pytest
Effective testing with pytest
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test community
 
Python testing using mock and pytest
Python testing using mock and pytestPython testing using mock and pytest
Python testing using mock and pytest
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con django
 
Benchy, python framework for performance benchmarking of Python Scripts
Benchy, python framework for performance benchmarking  of Python ScriptsBenchy, python framework for performance benchmarking  of Python Scripts
Benchy, python framework for performance benchmarking of Python Scripts
 
Full Stack Unit Testing
Full Stack Unit TestingFull Stack Unit Testing
Full Stack Unit Testing
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
Unit Testing from Setup to Deployment
Unit Testing from Setup to DeploymentUnit Testing from Setup to Deployment
Unit Testing from Setup to Deployment
 
MT_01_unittest_python.pdf
MT_01_unittest_python.pdfMT_01_unittest_python.pdf
MT_01_unittest_python.pdf
 
Running Intelligent Applications inside a Database: Deep Learning with Python...
Running Intelligent Applications inside a Database: Deep Learning with Python...Running Intelligent Applications inside a Database: Deep Learning with Python...
Running Intelligent Applications inside a Database: Deep Learning with Python...
 
Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023
 
關於測試,我說的其實是......
關於測試,我說的其實是......關於測試,我說的其實是......
關於測試,我說的其實是......
 
Defensive Apex Programming
Defensive Apex ProgrammingDefensive Apex Programming
Defensive Apex Programming
 
Spock Testing Framework - The Next Generation
Spock Testing Framework - The Next GenerationSpock Testing Framework - The Next Generation
Spock Testing Framework - The Next Generation
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
Mutation testing Bucharest Tech Week
Mutation testing Bucharest Tech WeekMutation testing Bucharest Tech Week
Mutation testing Bucharest Tech Week
 

Recently uploaded

A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZABSYZ Inc
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commercemanigoyal112
 

Recently uploaded (20)

A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZ
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commerce
 

pytest로 파이썬 코드 테스트하기

  • 1. PyCon Korea 2019 pytest로 파이썬 코드 테스트하기 최영선 yeongseon.choe@gmail.com
  • 3. • Modify Code with Confidence • Identify Bugs Early • Improve System Design https://alysivji.github.io/testing-101-introduction-to-testing.html#benefits-of- testing Why we should test code?
  • 4. • python test framework. • Advantages of pytest • Easy to use • Can run a specific test or subset of tests • Skip tests • Can run tests in parallel What is pytest?
  • 6. PyCon Korea 2019 1. Getting Started
  • 7. • Requirements • Python 3 • virtualenv • Installation Getting Started $ virtualenv –p python3.7 venv $ source virtualenv/bin/activate $ (venv)
  • 8. • An example of simple test • Execution # content of test_sample.py def inc(x): return x + 1 def test_answer(): assert int(3) == 5 $ pytest test_sample.py
  • 9. • (venv) py.test test_sample.py • (venv) py.test tests/test_sample.py • (venv) py.test tests/ How to run test cases? $ pytest -h usage: pytest [options] [file_or_dir] [file_or_dir] [...] positional arguments: file_or_dir
  • 11. # calculator.py def add(x, y): return x + y def subtract(x, y): return x - y def multiply(x, y): return x * y def divide(x, y): return x / y
  • 12. # calculator.py def add(x, y): return x + y def subtract(x, y): return x - y def multiply(x, y): return x * y def divide(x, y): return x / y # test_calculator.py import pytest from calculator import add, divide def test_add(): assert add(1, 2) == 3 assert not add (2, 2) == 3 def test_divide(): with pytest.raises(ZeroDivisionError): divide(1, 0)
  • 13. PyCon Korea 2019 2. Project Structure
  • 14. Structure of the Repository • Run test project/ sample/ __init__.py sample.py tests/ test_sample.py $ cd project $ python –m pytest tests/test_sample.py
  • 16. $ cd pytest_tutorial $ ls calculator.py test_calculator.py $ cd pytest_tutorial $ mkdir src $ mkdir tests $ mv caclculator.py src $ mv test_calculator.py tests $ pytest # edit code $ python –m pytest tests
  • 18. Test Fixture • A software test fixture sets up the system for the testing process by providing it with all the necessary code to initialize it, thereby satisfying whatever preconditions there may be. • Frequently fixtures are created by handling setUp() and tearDown() events of the unit testing framework. Four phases of a test: 1. Set-up 2. Exercise, interacting with the system under test 3. Verify, determining whether the expected outcome has been obtained 4. Tear down, to return to the original state
  • 19. • Fixtures are run pytest before the actual test functions. • @pytest.fixture() decorator • Purpose • Setup and Teardown for the tests (e.g, database) • Test set for the tests pytest fixtures
  • 21. # calculator.py class Calculator(object): """Calculator class""" def __init__(self): pass @staticmethod def add(a, b): return a + b @staticmethod def subtract(a, b): return a - b @staticmethod def multiply(a, b): return a * b @staticmethod def divide(a, b): return a / b
  • 22. # calculator.py class Calculator(object): """Calculator class""" def __init__(self): pass @staticmethod def add(a, b): return a + b @staticmethod def subtract(a, b): return a - b @staticmethod def multiply(a, b): return a * b @staticmethod def divide(a, b): return a / b # test_calculator.py from src.calculator import add def test_add(): assert add(1, 2) == 3
  • 23. # calculator.py class Calculator(object): """Calculator class""" def __init__(self): pass @staticmethod def add(a, b): return a + b @staticmethod def subtract(a, b): return a - b @staticmethod def multiply(a, b): return a * b @staticmethod def divide(a, b): return a / b # test_calculator.py from src.calculator import Calculator def test_add(): calculator = Calculator() assert calculator.add(1, 2) == 3 assert calculator.add(2, 2) == 4 def test_subtract(): calculator = Calculator() assert calculator.subtract(5, 1) == 4 assert calculator.subtract(3, 2) == 1 def test_multiply(): calculator = Calculator() assert calculator.multiply(2, 2) == 4 assert calculator.multiply(5, 6) == 30 def test_divide(): calculator = Calculator() assert calculator.divide(8, 2) == 4 assert calculator.divide(9, 3) == 3
  • 24. # test_calculator.py from src.calculator import Calculator def test_add(): calculator = Calculator() assert calculator.add(1, 2) == 3 assert calculator.add(2, 2) == 4 def test_subtract(): calculator = Calculator() assert calculator.subtract(5, 1) == 4 assert calculator.subtract(3, 2) == 1 def test_multiply(): calculator = Calculator() assert calculator.multiply(2, 2) == 4 assert calculator.multiply(5, 6) == 30 def test_divide(): calculator = Calculator() assert calculator.divide(8, 2) == 4 assert calculator.divide(9, 3) == 3
  • 25. # test_calculator.py from src.calculator import Calculator @pytest.fixture def calculator(): calculator = Calculator() return calculator def test_add(calculator): assert calculator.add(1, 2) == 3 assert calculator.add(2, 2) == 4 def test_subtract(calculator): assert calculator.subtract(5, 1) == 4 assert calculator.subtract(3, 2) == 1 def test_multiply(calculator): assert calculator.multiply(2, 2) == 4 assert calculator.multiply(5, 6) == 30
  • 26. # confest.py import pytest from src.calculator import Calculator @pytest.fixture def calculator(): calculator = Calculator() return calculator # test_calculator.py from src.calculator import Calculator @pytest.fixture def calculator(): calculator = Calculator() return calculator def test_add(calculator): assert calculator.add(1, 2) == 3 assert calculator.add(2, 2) == 4 def test_add_fail(calculator): assert calculator.add(1, 2) != 6 assert calculator.add(2, 2) != 5 def test_multiply(calculator): assert calculator.multiply(2, 2) == 4 assert calculator.multiply(5, 6) == 30
  • 27. # test_calculator.py from src.calculator import Calculator def test_add(calculator): assert calculator.add(1, 2) == 3 assert calculator.add(2, 2) == 4 def test_add_fail(calculator): assert calculator.add(1, 2) != 6 assert calculator.add(2, 2) != 5
  • 28. PyCon Korea 2019 4. Parameterize
  • 29. pytest parameterize • Define multiple sets of arguments and fixtures at the test function or class. • @pytest.mark.parametrize: parametrizing test functions • The builtin pytest.mark.parametrize decorator
  • 31. # test_calculator.py from src.calculator import Calculator def test_add(calculator): assert calculator.add(1, 2) == 3 assert calculator.add(2, 2) == 4 assert calculator.add(2, 2) == 4 pytest.mark.parametrize(argnames, argvalues)
  • 32. # test_calculator.py from src.calculator import Calculator def test_add(calculator): assert calculator.add(1, 2) == 3 assert calculator.add(2, 2) == 4 assert calculator.add(9, 2) == 11 @pytest.mark.parametrize( "a, b, expected", [(1, 2, 3), (2, 2, 4), (2, 7, 11)]) def test_add_fail(calculator, a, b, expected): assert calculator.add(a, b) != expected
  • 33. # test_calculator.py from src.calculator import Calculator @pytest.mark.parametrize( "a, b, expected", [(1, 2, 6), (2, 2, 5), (2, 7, 2)]) def test_add_fail(calculator, a, b, expected): assert calculator.add(a, b) != expected @pytest.mark.xfail(rason="wrong result") @pytest.mark.parametrize( "a, b, expected", [(1, 2, 6), (2, 2, 5), (2, 7, 2)]) def test_add_fail(calculator, a, b, expected): assert calculator.add(a, b) == expected
  • 34. • Buildin markers: skip, skipif and fail • skip: enable you to skip tests you don’t want to run • @pytest.mark.skip(reason=‘something’) • @pytest.mark.skipif(condition, reason=‘something’) • xfail: we are telling pytest to run a test function, but we expect it to fail. • @pytest.mark.fail
  • 35. # test_calculator.py from src.calculator import Calculator @pytest.mark.xfail(rason="wrong result") @pytest.mark.parametrize( "a, b, expected", [(1, 2, 6), (2, 2, 5), (2, 7, 2)]) def test_add_fail(calculator, a, b, expected): assert calculator.add(a, b) == expected @pytest.mark.parametrize( "a, b, expected", [pytest.param(1, 2, 6, marks=pytest.mark.xfail), pytest.param(2, 2, 5, marks=pytest.mark.xfail), pytest.param(2, 7, 2, marks=pytest.mark.xfail)]) def test_add_fail(calculator, a, b, expected): assert calculator.add(a, b) == expected
  • 36. # test_calculator.py from src.calculator import Calculator @pytest.mark.parametrize( "a, b, expected", [(1, 2, 3), (2, 2, 4), (2, 7, 9), pytest.param(1, 2, 6, marks=pytest.mark.xfail), pytest.param(2, 2, 5, marks=pytest.mark.xfail), pytest.param(2, 7, 2, marks=pytest.mark.xfail)]) def test_add(calculator, a, b, expected): assert calculator.add(a, b) == expected
  • 37. # test_calculator.py from src.calculator import Calculator add_test_data = [ (1, 2, 3), (2, 2, 4), (2, 7, 9), pytest.param(1, 2, 6, marks=pytest.mark.xfail), pytest.param(2, 2, 5, marks=pytest.mark.xfail), pytest.param(2, 7, 2, marks=pytest.mark.xfail) ] @pytest.mark.parametrize( "a, b, expected", add_test_data) def test_add(calculator, a, b, expected): assert calculator.add(a, b) == expected
  • 38. • ids: optional parameter to parameterize() • @pytest.mark.parameterize() decorator • pytest.param(<value>, id=“something”)
  • 39. # test_calculator.py from src.calculator import Calculator add_test_data = [ (1, 2, 3), (2, 2, 4), (2, 7, 9), pytest.param(1, 2, 6, marks=pytest.mark.xfail), pytest.param(2, 2, 5, marks=pytest.mark.xfail), pytest.param(2, 7, 2, marks=pytest.mark.xfail)] @pytest.mark.parametrize( "a, b, expected", add_test_data, ids=[ "1 add 2 is 3", "2 add 2 is 4", "2 add 7 is 9", "1 add 2 is not 6", "2 add 2 is not 5", "2 add 7 is not 2"] ) def test_add(calculator, a, b, expected): assert calculator.add(a, b) == expected
  • 40. # test_calculator.py from src.calculator import Calculator add_test_data = [ (1, 2, 3), (2, 2, 4), (2, 7, 9), pytest.param(1, 2, 6, marks=pytest.mark.xfail), pytest.param(2, 2, 5, marks=pytest.mark.xfail), pytest.param(2, 7, 2, marks=pytest.mark.xfail)] @pytest.mark.parametrize( "a, b, expected", add_test_data, ids=[ "1 add 2 is 3", "2 add 2 is 4", "2 add 7 is 9", "1 add 2 is not 6", "2 add 2 is not 5", "2 add 7 is not 2"] ) def test_add(calculator, a, b, expected): assert calculator.add(a, b) == expected
  • 41. # test_calculator.py from src.calculator import Calculator subtract_test_data = [ pytest.param(5, 1, 4, id="5 subtract 1 is 4"), pytest.param(3, 2, 1, id="3 subtract 2 is 1"), pytest.param(10, 2, 8, id="10 subtract 2 is 8"), pytest.param(5, 1, 6, marks=pytest.mark.xfail, id="5 subtract 1 is 6"), pytest.param(3, 2, 2, marks=pytest.mark.xfail, id="3 subtract 2 is 2"), pytest.param(10, 2, 1, marks=pytest.mark.xfail, id="10 subtract 2 is 1") ] @pytest.mark.parametrize( "a, b, expected", subtract_test_data ) def test_subtract(calculator, a, b, expected): assert calculator.subtract(a, b) == expected
  • 43. • Thirty-party pytest plugin • pytest-mock • Swapping out part of the system to isolate bits of code • Mock objects: test doubles, spies, fakes, or stubs.. • mock.patch • mock.patch.object pytest mock
  • 45. • Installation $ (venv) pip install pytest-mock
  • 46. def test_add_with_mocker1(mocker, calculator): """Test functionality of add.""" mocker.patch.object(calculator, 'add', return_value=5) assert calculator.add(1, 2) is 5 assert calculator.add(2, 2) is 5 def test_add_with_mocker2(mocker, calculator): """Test functionality of add.""" mocker.patch.object(calculator, 'add', side_effect=[1, 2]) assert calculator.add(1, 2) is 1 assert calculator.add(2, 2) is 2 def test_add_with_mocker3(mocker, calculator): """Test functionality of add.""" mocker.patch.object(calculator, 'add', side_effect=ZeroDivisionError()) with pytest.raises(ZeroDivisionError): calculator.add(1, 2)
  • 47. # calculator.py import logging logging.basicConfig(level=logging.INFO) class Calculator(): """Calculator class""" def __init__(self): self.logger = logging.getLogger(self.__class__.__name__) def add(self, a, b): self.logger.info( "add {a} to {b} is {result}".format( a=a, b=b, result=a + b )) return a + b
  • 48. @pytest.mark.parametrize( "a, b, expected", add_test_data ) # mocker: The mocker fixture is provided by the pytest-mock plugin def test_add_spy_logger(mocker, calculator, a, b, expected): spy_info = mocker.spy(calculator.logger, "info") assert calculator.add(a, b) == expected assert spy_info.called assert spy_info.call_count == 1 calls = [mocker.call("add {a} to {b} is {expected}".format( a=a, b=b, expected=expected ))] assert spy_info.call_args_list == calls
  • 49. References • https://docs.pytest.org/en/latest/ • https://docs.python-guide.org/writing/structure/ • https://stackoverflow.com/questions/1896918/running-unittest-with-typical- test-directory-structure • https://www.slideshare.net/soasme/pytest • https://github.com/pytest-dev/pytest-mock/