4. pytest is a mature full-featured Python testing tool that helps you write better programs.
An example of a simple test:
pytest 란?
# content of test_sample.py
def inc(x):
return x + 1
def test_answer():
assert inc(3) == 5
$ pytest
=========================== test session starts ============================
test_sample.py F [100%]
================================= FAILURES =================================
_______________________________ test_answer ________________________________
def test_answer():
> assert inc(3) == 5
E assert 4 == 5
E + where 4 = inc(3)
test_sample.py:6: AssertionError
============================ 1 failed in 0.12s =============================
https://docs.pytest.org/en/latest/
5. ● Detailed info on failing assert statements (no need to remember self.assert* names);
● Auto-discovery of test modules and functions;
● Modular fixtures for managing small or parametrized long-lived test resources;
● Can run unittest (including trial) and nose test suites out of the box;
● Python 3.5+ and PyPy 3;
● Rich plugin architecture, with over 315+ external plugins and thriving community;
pytest 특징 (vs unittest)
7. test 작성하기
# content of test_class.py
class TestClass:
def test_one(self):
x = "this"
assert "h" in x
def test_two(self):
x = "hello"
assert hasattr(x, "check")
# content of test_sample.py
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
1. test prefixed test functions or methods outside of class
2. test prefixed test functions or methods inside Test prefixed test classes
(without an __init__ method)
8. fixture 란?
The purpose of test fixtures is to provide a fixed baseline upon which tests can reliably and
repeatedly execute.
● fixtures have explicit names and are activated by declaring their use from test functions,
modules, classes or whole projects.
● fixtures are implemented in a modular manner, as each fixture name triggers a fixture
function which can itself use other fixtures.
● fixture management scales from simple unit to complex functional testing, allowing to
parametrize fixtures and tests according to configuration and component options, or to
re-use fixtures across function, class, module or whole test session scopes.
11. ● If during implementing your tests you realize that
you want to use a fixture function from multiple
test files you can move it to a conftest.py file.
● You don’t need to import the fixture you want to
use in a test, it automatically gets discovered by
pytest.
● The discovery of fixture functions starts at test
classes, then test modules, then conftest.py files
and finally builtin and third party plugins.
conftest.py - fixture 공유하기
# content of alice/conftest.py
@pytest.fixture
def hello():
return “hello”
# content of alice/test_1.py
def test_1(hello):
assert hello == “hello”
# content of alice/test_2.py
def test_2(hello):
assert hello != “hi”
~/alice/
12. conftest.py - fixture 공유하기
# content of bob/test.py
def test_3(hello):
assert hello == “hello”
$ pytest
=========================== test session starts ============================
alice/test_1.py . [ 33%]
alice/test_2.py . [ 67%]
bob/test_3.py E [100%]
================================= FAILURES =================================
_______________________________ test_answer ________________________________
file /bob/test_3.py, line 2
def test_3(hello):
E fixture ‘hello’ not found
============================ 1 failed in 0.12s =============================
~/alice/ ~/bob/
# Conftest.py
@pytest.fixture
def hello():
# Test_1.py
def
test_1(hello):
# Test_2.py
def
test_2(hello):
13. pytest-django: Django 테스트용 fixture를 제공
https://pytest-django.readthedocs.io/
pytest-cov: Code coverage 를 체크
https://pytest-cov.readthedocs.io/
pytest-xdist: 분산처리를 통한 테스트를 진행
https://github.com/pytest-dev/pytest-xdist
pytest-selenium: 웹 테스트를 위한 Selenium 에 대한 fixture를 제공
https://pytest-selenium.readthedocs.io/
pytest plugin
17. Hmm…?
1. 우직하게 그냥 진행한다 (Bob이 죽을 거 같지만 일단 귀차니즘 해결)
2. Alice의 테스트를 위한 테스트용 서버를 따로 생성한다 (하드웨어가 남는다면?)
3. 내가 필요한 요청에 대해서만 적절한 응답을 주는 가상의 서버를 생성한다 (mock server)
4. 보내는 requests 를 Hijacking하여 가짜 응답을 제공한다 (mock requests)
19. responses
A utility library for mocking out the requests Python library.
The core of responses comes from registering mock responses:
import responses
import requests
@responses.activate
def test_simple():
responses.add(responses.GET, 'http://twitter.com/api/1/foobar',
json={'error': 'not found'}, status=404)
resp = requests.get('http://twitter.com/api/1/foobar')
assert resp.json() == {"error": "not found"}
https://github.com/getsentry/responses
20. aioresponses
Aioresponses is a helper to mock/fake web requests in python aiohttp package.
import asyncio
import aiohttp
from aioresponses import aioresponses
def test_ctx():
loop = asyncio.get_event_loop()
session = aiohttp.ClientSession()
with aioresponses() as m:
m.get('http://test.example.com', payload=dict(foo='bar'))
resp = loop.run_until_complete(session.get('http://test.example.com'))
data = loop.run_until_complete(resp.json())
assert dict(foo='bar') == data
https://github.com/pnuckowski/aioresponses
23. tox 란?
tox is a generic virtualenv management and test command line tool you can use for:
● checking your package installs correctly with different Python versions and interpreters
● running your tests in each of the environments, configuring your test tool of choice
● acting as a frontend to Continuous Integration servers, greatly reducing boilerplate and
merging CI and shell-based testing.
https://tox.readthedocs.io/en/latest/
24. setup.py - tox 설정하기
from setuptools import setup
setup(name='insight-backend',
version=__version__)
tox 에서 사용하는 virtualenv 에 대한 설정 파일
25. tox.ini - tox 설정하기
# content of: tox.ini , put in same dir as setup.py
[tox]
envlist = py27,py36
[testenv]
# install pytest in the virtualenv where commands will be executed
deps = pytest
commands =
# NOTE: you can run any command line tool here - not just tests
pytest
https://tox.readthedocs.io/en/latest/config.html
26. tox 실행하기
$ tox
[lots of output from what tox does]
[lots of output from commands that were run]
__________________ summary _________________
py27: commands succeeded
py37: commands succeeded
congratulations :)