ãŸããã
æŽå²çãªè·æ¥ã«ãããšãç§ã¯SQL-schikã§ãã ããããéåœã¯ç§ãBigDataã«é£ããŠè¡ãããã®åŸãèŠåŽããŸãã-JavaãPythonãããã³é¢æ°åããã°ã©ãã³ã°ãç¿åŸããŸããïŒScalaã®åŠç¿ããªã¹ãã«èŒã£ãŠããŸãïŒã å®éããããžã§ã¯ãã®äžéšã§ãPythonã³ãŒãããã¹ãããå¿
èŠãçããŸããã QAã®ã¹ã¿ããã¯ãããã®ç®çã®ããã«PyTestã«å©èšããŸãããããã®ç£ããªãè¯ãã®ããæç¢ºã«çããããšã¯é£ãããšæããŸããã æ®å¿µãªããããã·ã¢èªã®ã»ã°ã¡ã³ãã§ã¯ããã®åé¡ã«é¢ããæ
å ±ã¯ããã»ã©å€ããããŸãã
ãYandexã§ã©ã®ããã«äœ¿çšãããŠããã ããã¹ãŠãè¯ãæ¹æ³ã§ãã åæã«ããã®èšäºã§èª¬æãããŠãããã®ã¯ããã®éã«æ²¿ã£ãŠæ
ãå§ãã人ã«ãšã£ãŠã¯ããªãè€éã«èŠããŸãã å
¬åŒã®ããã¥ã¡ã³ãã¯èšããŸã§ããããŸããããã¢ãžã¥ãŒã«èªäœãä»ã®ãœãŒã¹ããèŠã€ããåŸã«åããŠæå³ããããŸããã ç§ã¯ãè峿·±ãããšã¯ããã«æžãããŠãããšã¯èšããŸããããæ®å¿µãªãããæåã¯ãŸã£ããããã§ã¯ãããŸããã
PythonãŠããããã¹ã
ãããäœã§ããããªãç§ãäŒããã¹ããã€ã³ããèŠããªãã®ã-ãŠã£ãããã£ã¢ã¯ãŸã ãã£ãšç¥ã£ãŠããŸãã Pythonã®æ¢åã®ã¢ãžã¥ãŒã«ã«é¢ããŠã¯ã
Habréã§è©³ãã説æãããŠããŸã ã
å¿
èŠãªç¥èã®ç޹ä»
説æããæç¹ã§ãPythonã®ç§ã®ç¥èã¯éåžžã«è¡šé¢çã§ãã-ããã€ãã®ç°¡åãªã¢ãžã¥ãŒã«ãäœæããæšæºçãªãã®ãç¥ã£ãŠããŸããã ããããPyTestãšã®è¡çªã§ã
ãããš
ãã ããããŠ
yieldæ§é äœã§ç¥èããŒã¹ããã³ã¬ãŒã¿ãŒ
ã§è£å
ããå¿
èŠããããŸããã
PyTestã®é·æãšçæ
1ïŒAPIããã®ç¬ç«ïŒå®åãªãïŒã åãunittestã§ã³ãŒããã©ã®ããã«èŠãããïŒ
ã³ãŒãimport unittest class TestUtilDate(unittest.TestCase): def setUp(self):
PyTestã§ãåãããšïŒ
ã³ãŒã import pytest def setup_module(module):
2ïŒè©³çްã¬ããŒãã JUnitXMLãžã®ã¢ããããŒããå«ãïŒJenkinsãšã®çµ±åçšïŒã ã¬ããŒãèªäœã®ã¿ã€ãã¯ã远å ã®ã¢ãžã¥ãŒã«ã«ãã£ãŠå€æŽã§ããŸãïŒè²ãå«ãïŒïŒãããã«ã€ããŠã¯åŸã§å¥é説æããŸãïŒã ãŸããäžè¬çã«ã¯ãã³ã³ãœãŒã«ã®ã«ã©ãŒã¬ããŒãã®æ¹ã䟿å©ã§ããèµ€ã®FAILEDã¯ããã«è¡šç€ºãããŸãã

3ïŒäŸ¿å©ãªã¢ãµãŒãïŒPythonã®æšæºïŒã ç°ãªãassert'ovã®æå
šäœãèŠããŠããå¿
èŠã¯ãããŸããã
4ïŒãã¹ãŠã®ã¬ãã«ã®åçãªãã£ã¯ã¹ãã£ãããã¯ãèªåçã«ç¹å®ã®ãã¹ãã®ããã«åŒã³åºãããšãã§ããŸãã
5ïŒãã£ã¯ã¹ãã£ã®è¿œå æ©èœïŒæ»ãå€ããã¡ã€ãã©ã€ã¶ãã¹ã³ãŒãããªã¯ãšã¹ããªããžã§ã¯ããèªå䜿çšããã¹ãããããã£ã¯ã¹ãã£ïŒ
6ïŒãã¹ãã®ãã©ã¡ãŒã¿ãŒåãã€ãŸããç°ãªããã©ã¡ãŒã¿ãŒã»ããã䜿çšããåããã¹ãã®èµ·åã äžè¬çã«ãããã¯ãã©ã°ã©ã5ãè¿œå æ©èœãã£ã¯ã¹ãã£ããæããŸãããå¥ã®ãã©ã°ã©ãã«å€ããã»ã©æ©äŒãå€ãã®ã§ãã
7ïŒããŒã¯ããã¹ããã¹ããããããããã¹ãã倱æãšããŠããŒã¯ãããïŒããã¯éçºäžã«äŸ¿å©ãªäºæ³ãããåäœã§ãïŒããã¹ãã¹ã€ãŒãã«ååãä»ããŠååã§ã®ã¿å®è¡ã§ããããã«ããŸãã
8ïŒãã©ã°ã€ã³ã ãã®ã¢ãžã¥ãŒã«ã«ã¯ãåå¥ã«ã€ã³ã¹ããŒã«ã§ãã远å ã¢ãžã¥ãŒã«ã®ããªã倧ããªãªã¹ãããããŸãã
9ïŒunittestããã³noseã§èšè¿°ããããã¹ããå®è¡ããæ©èœãã€ãŸããããããšã®å®å
šãªäžäœäºææ§ã
æ¬ ç¹ã«ã€ããŠã¯ãå€ãã¯ãããŸããããæ¬¡ã®ããã«èšããŸãã
1ïŒè¿œå ã¬ãã«ã®ãã¹ãã®æ¬ åŠïŒãã¹ãã®ã¢ãžã¥ãŒã«ãã¯ã©ã¹ãã¡ãœããã颿°ã«ã¯ãé©åãªã¬ãã«ããããŸãã ãã ããåã颿°ãè€æ°ã®ãã¹ãã±ãŒã¹ãæã€ããšãã§ããå ŽåïŒããšãã°ãæ»ãå€ãšãšã©ãŒã®ãã§ãã¯ïŒãããžãã¯ã«ã¯è¿œå ã¬ãã«ã®ãã¹ãã±ãŒã¹ãå¿
èŠã§ãã ããã¯ã远å ã®ã¢ãžã¥ãŒã«ïŒãã©ã°ã€ã³ïŒpytest-describeã«ãã£ãŠéšåçã«è£ãããŸãããé©åãªã¬ãã«ã®ãã£ã¯ã¹ãã£ãŒããªããšããåé¡ãçºçããŸãïŒscope =â describeâïŒã ãã¡ãããããã§çããããšã¯ã§ããŸãããç¶æ³ã«ãã£ãŠã¯ãPyTestã®äž»ãªååãåçŽããšäŸ¿å©ãã®ããã®ãã¹ãŠãã«éåããå¯èœæ§ããããŸãã
2ïŒçç£ãå«ããã¢ãžã¥ãŒã«ã®åå¥ã®ã€ã³ã¹ããŒã«ã®å¿
èŠæ§ã ããã§ããunittestãšdoctestã¯åºæ¬çãªPythonããŒã«ãããã®äžéšã§ããã远å ã®ãžã§ã¹ãã£ãŒã¯å¿
èŠãããŸããã
3ïŒPyTestã䜿çšããã«ã¯ãåããŠããããã¹ããããPythonã®ç¥èãå°ãå¿
èŠã§ãïŒãå¿
èŠãªç¥èã®æŠèŠããåç
§ïŒã
ã«ããã®äžã®ã¢ãžã¥ãŒã«ãšãã®æ©èœã®è©³çްãªèª¬æã
ãã¹ããå®è¡ãã
unittestã®å Žåãã¡ã€ã³é¢æ°åŒã³åºãã䜿çšãããŸãã ãããã£ãŠãèµ·åã¯ãpython unittest_example.pyããšãã圢åŒã«ãªããŸãã åæã«ããã¹ãã¹ã€ãŒããå®è¡ããã«ã¯ãTestSuitã§ããããåå¥ã«çµã¿åãããŠå®è¡ããå¿
èŠããããŸãã PyTestã¯ããã©ã«ãå
ã®ãã¹ãŠã®ãã¡ã€ã«ïŒååž°çã«ãµããã©ã«ãããã©ããŒã¹ããïŒãŸãã¯æå®ããããã¡ã€ã«ã«ã€ããŠãç¬èªã®ååtest_ *ïŒã¯ã©ã¹åã®Test_ *ïŒã§ãã¹ãŠã®ãã¹ããåéããŸãã ã€ãŸããåŒã³åºãäŸã¯ãpy.test -v pytest_example.pyãã®ããã«ãªããŸã
åºæ¬çãªåå
ãã®å Žåããã£ã¯ã¹ãã£ã¯ããã¹ãã«é©åãªç°å¢ãäœæããããã«èµ·åããã颿°ãšã¡ãœãããåŒã³åºããŸãã unittestãšåæ§ã«ãPyTestã«ã¯ãã¹ãŠã®ã¬ãã«ã®ãã£ã¯ã¹ãã£ã®ååããããŸãã
import pytest def setup(): print ("basic setup into module") def teardown(): print ("basic teardown into module") def setup_module(module): print ("module setup") def teardown_module(module): print ("module teardown") def setup_function(function): print ("function setup") def teardown_function(function): print ("function teardown") def test_numbers_3_4(): print "test 3*4" assert 3*4 == 12 def test_strings_a_3(): print "test a*3" assert 'a'*3 == 'aaa' class TestUM: def setup(self): print ("basic setup into class") def teardown(self): print ("basic teardown into class") def setup_class(cls): print ("class setup") def teardown_class(cls): print ("class teardown") def setup_method(self, method): print ("method setup") def teardown_method(self, method): print ("method teardown") def test_numbers_5_6(self): print "test 5*6" assert 5*6 == 30 def test_strings_b_2(self): print "test b*2" assert 'b'*2 == 'bb'
printã³ãã³ãã«ãã£ãŠçæããããã¹ãŠã®åºåã衚瀺ããã«ã¯ã-sãã©ã°ãæå®ããŠãã¹ããå®è¡ããå¿
èŠããããŸãã
tmp>py.test -s basic_fixtures.py
ãã®äŸã¯ãåãã£ã¯ã¹ãã£ã¬ãã«ã®éå±€ãšåçŸæ§ãå®å
šã«ç€ºããŠããŸãïŒããšãã°ãsetup_functionã¯å颿°åŒã³åºãã®åã«åŒã³åºãããsetup_moduleã¯ã¢ãžã¥ãŒã«å
šäœã«å¯ŸããŠ1åã ãåŒã³åºãããŸãïŒã ããã©ã«ãã®ãã£ã¯ã¹ãã£ã¬ãã«ã颿°/ã¡ãœããïŒãã£ã¯ã¹ãã£ã®ã»ããã¢ãããšåè§£ïŒã§ããããšãããããŸãã
æ¡åŒµãã£ã¯ã¹ãã£
åé¡ã¯ãäžéšã®ãã¹ãã§ç¹å®ã®ç°å¢ãå¿
èŠã§ããããä»ã®ãã¹ãã§ã¯å¿
èŠãªãå Žåã¯ã©ãããã°ããããšããããšã§ãã ç°ãªãã¢ãžã¥ãŒã«ãŸãã¯ã¯ã©ã¹ã«åºãããŸããïŒ ããã¯éåžžã«å¿«é©ã§çŸããèŠããŸããã æ¡åŒµPyTestãã£ã¯ã¹ãã£ã圹ç«ã¡ãŸãã
ãããã£ãŠãPyTestã§æ¡åŒµãã£ã¯ã¹ãã£ãäœæããã«ã¯ã次ã®ãã®ãå¿
èŠã§ãã
1ïŒpytestã¢ãžã¥ãŒã«ãã€ã³ããŒããã
2ïŒ@ pytest.fixtureïŒïŒãã³ã¬ãŒã¿ã䜿çšããŠããã®é¢æ°ããã£ã¯ã¹ãã£ã§ããããšã瀺ããŸã
3ïŒãã£ã¯ã¹ãã£ïŒã¹ã³ãŒãïŒã®ã¬ãã«ãèšå®ããŸãã å¯èœãªå€ã¯ãã颿°ãããclsãããã¢ãžã¥ãŒã«ãããã»ãã·ã§ã³ãã§ãã ããã©ã«ãå€=ã颿°ãã
4ïŒãã®ãã£ã¯ã¹ãã£ã®ãã£ã¢ããŠã³ãåŒã³åºãå¿
èŠãããå Žåããã¡ã€ãã©ã€ã¶ã远å ããå¿
èŠããããŸãïŒãã£ã¯ã¹ãã£ã«æž¡ããããªã¯ãšã¹ããªããžã§ã¯ãã®addfinalizerã¡ãœãããŸãã¯yieldæ§æäœã䜿çšããŠïŒ
5ïŒãã®ãã£ã¯ã¹ãã£ã®ååã颿°ãã©ã¡ãŒã¿ãŒã®ãªã¹ãã«è¿œå ããŸã
import pytest @pytest.fixture() def resource_setup(request): print("resource_setup") def resource_teardown(): print("resource_teardown") request.addfinalizer(resource_teardown) def test_1_that_needs_resource(resource_setup): print("test_1_that_needs_resource") def test_2_that_does_not(): print("test_2_that_does_not") def test_3_that_does_again(resource_setup): print("test_3_that_does_again")
以äžãéå§ããŸãã
tmp>py.test -s extended_fixture.py
é«åºŠãªãã£ã¯ã¹ãã£ãåŒã³åºã
é«åºŠãªãã£ã¯ã¹ãã£ã¯ãããã«2ã€ã®æ¹æ³ã§åŒã³åºãããšãã§ããããšã«æ³šæããŠãã ããã
1ïŒãã³ã¬ãŒã¿@ pytest.mark.usefixturesïŒïŒã§ãã¹ããè£
食ãã
2ïŒãã£ã¯ã¹ãã£ã«èªå䜿çšãã©ã°ã䜿çšããŸãã ãã ããäºæããªããã¹ãåäœãçºçããå¯èœæ§ãããããããã®æ©èœã¯æ³šæããŠäœ¿çšããå¿
èŠããããŸãã
3ïŒãã¹ããã©ã¡ãŒã¿ãä»ããäžèšã®æ¹æ³
åã®äŸã次ã«ç€ºããŸãã
import pytest @pytest.fixture() def resource_setup(request): print("resource_setup") def resource_teardown(): print("resource_teardown") request.addfinalizer(resource_teardown) @pytest.fixture(scope="function", autouse=True) def another_resource_setup_with_autouse(request): print("another_resource_setup_with_autouse") def resource_teardown(): print("another_resource_teardown_with_autouse") request.addfinalizer(resource_teardown) def test_1_that_needs_resource(resource_setup): print("test_1_that_needs_resource") def test_2_that_does_not(): print("test_2_that_does_not") @pytest.mark.usefixtures("resource_setup") def test_3_that_does_again(): print("test_3_that_does_again")
以äžãéå§ããŸãã
tmp>py.test -s call_extended_fixtures.py
åè§£æ¡åŒµåšå
·
äžèšã®ããã«ãç¹å®ã®æ¡åŒµãã£ã¯ã¹ãã£ã«å¯ŸããŠãã£ã¢ããŠã³ãåŒã³åºãå¿
èŠãããå Žåã2ã€ã®æ¹æ³ã§å®è£
ã§ããŸãã
1ïŒãã¡ã€ãã©ã€ã¶ããã£ã¯ã¹ãã£ã«è¿œå ããŸãïŒãã£ã¯ã¹ãã£ã«æž¡ããããªã¯ãšã¹ããªããžã§ã¯ãã®addfinalizerã¡ãœãããä»ããŠïŒ
2ïŒyieldã³ã³ã¹ãã©ã¯ãã䜿çšããŠïŒPyTestããŒãžã§ã³2.4以éïŒ
æ¡åŒµãã£ã¯ã¹ãã£ãäœæããäŸã§æ€èšããæåã®æ¹æ³ã 次ã«ãyieldã䜿çšããŠåãæ©èœãå®èšŒããŸãã 颿°ããã£ã¯ã¹ãã£ãšããŠè£
食ãããšãã«yieldã䜿çšããã«ã¯ã@ pytest.fixtureïŒïŒã§ã¯ãªã@ pytest.yield_fixtureïŒïŒãã³ã¬ãŒã¿ã䜿çšããå¿
èŠãããããšã«æ³šæããŠãã ããã
import pytest @pytest.yield_fixture() def resource_setup(): print("resource_setup") yield print("resource_teardown") def test_1_that_needs_resource(resource_setup): print("test_1_that_needs_resource") def test_2_that_does_not(): print("test_2_that_does_not") def test_3_that_does_again(resource_setup): print("test_3_that_does_again")
ãã¡ã€ãã©ã€ã¶ãªãã·ã§ã³ãšäžèŽãããããããã¹ãã«çµè«ã远å ããŸããã
ãã£ã¯ã¹ãã£ã®æ»ãå€
ãªãã·ã§ã³ãšããŠãPyTestã®ãã£ã¯ã¹ãã£ã¯returnãä»ããŠãã¹ãã«äœããè¿ãããšãã§ããŸãã äœããã®ç¶æ
å€ãŸãã¯ãªããžã§ã¯ãïŒãã¡ã€ã«ãªã©ïŒã«ãªããŸãã
import pytest @pytest.fixture(scope="module") def resource_setup(request): print("\nconnect to db") db = {"Red":1,"Blue":2,"Green":3} def resource_teardown(): print("\ndisconnect") request.addfinalizer(resource_teardown) return db def test_db(resource_setup): for k in resource_setup.keys(): print "color {0} has id {1}".format(k, resource_setup[k]) def test_red(resource_setup): assert resource_setup["Red"] == 1 def test_blue(resource_setup): assert resource_setup["Blue"] != 1
以äžãéå§ããŸãã
tmp>py.test -v -s return_value.py
ãã£ã¯ã¹ãã£ã¬ãã«ïŒã¹ã³ãŒãïŒ
ãã£ã¯ã¹ãã£ã¬ãã«ã¯ãã颿°ãããclsãããã¢ãžã¥ãŒã«ãããã»ãã·ã§ã³ãã®å€ãåããŸãã ããã©ã«ãå€=ã颿°ã\
æ©èœ-åãã¹ãã®ãã£ã¯ã¹ãã£å®è¡
cls-åã¯ã©ã¹ã®ãã£ã¯ã¹ãã£å®è¡
ã¢ãžã¥ãŒã«-åã¢ãžã¥ãŒã«ã«å¯ŸããŠãã£ã¯ã¹ãã£ãèµ·åãããŸã
ã»ãã·ã§ã³-ãã£ã¯ã¹ãã£ã¯ã»ãã·ã§ã³ããšã«èµ·åãããŸãïŒã€ãŸããå®éã«ã¯1åïŒ
ããšãã°ãåã®äŸã§ã¯ãã¹ã³ãŒããæ©èœã«å€æŽãããã¹ãããšã«ããŒã¿ããŒã¹æ¥ç¶ãåŒã³åºããŠåæã§ããŸãã
import pytest @pytest.fixture(scope="function") def resource_setup(request): print("\nconnect to db") db = {"Red":1,"Blue":2,"Green":3} def resource_teardown(): print("\ndisconnect") request.addfinalizer(resource_teardown) return db def test_db(resource_setup): for k in resource_setup.keys(): print "color {0} has id {1}".format(k, resource_setup[k]) def test_red(resource_setup): assert resource_setup["Red"] == 1 def test_blue(resource_setup): assert resource_setup["Blue"] != 1
tmp>py.test -v -s scope.py
ãã£ã¯ã¹ãã£ã¯ãPyTestã«ãã£ãŠèªåçã«ã€ã³ããŒããããconftest.pyãã¡ã€ã«ã§ã説æã§ããŸãã ãã®å Žåããã£ã¯ã¹ãã£ã«ã¯ä»»æã®ã¬ãã«ãèšå®ã§ããŸãïŒãã®ãã¡ã€ã«ã®èª¬æãä»ããŠã®ã¿ããã»ãã·ã§ã³ãã¬ãã«ã®ãã£ã¯ã¹ãã£ãäœæã§ããŸãïŒã
ããšãã°ãconftest.pyãã¡ã€ã«ãš2ã€ã®ãã¹ããã¡ã€ã«ã§åå¥ã®ã»ãã·ã§ã³ã¹ã³ãŒããã©ã«ããŒãäœæããŸãïŒPyTestãã¢ãžã¥ãŒã«ãèªåçã«ã€ã³ããŒãããã«ã¯ãã¢ãžã¥ãŒã«ã®ååãtest_ã§å§ãŸãå¿
èŠããããŸãããã®åäœã¯å€æŽã§ããŸããïŒã
conftest.pyïŒ import pytest @pytest.fixture(scope="session", autouse=True) def auto_session_resource(request): """ Auto session resource fixture """ print("auto_session_resource_setup") def auto_session_resource_teardown(): print("auto_session_resource_teardown") request.addfinalizer(auto_session_resource_teardown) @pytest.fixture(scope="session") def manually_session_resource(request): """ Manual set session resource fixture """ print("manually_session_resource_setup") def manually_session_resource_teardown(): print("manually_session_resource_teardown") request.addfinalizer(manually_session_resource_teardown) @pytest.fixture(scope="function") def function_resource(request): """ Function resource fixture """ print("function_resource_setup") def function_resource_teardown(): print("function_resource_teardown") request.addfinalizer(function_resource_teardown)
test_session_scope1.py import pytest def test_1_that_does_not_need_session_resource(): print("test_1_that_does_not_need_session_resource") def test_2_that_does(manually_session_resource): print("test_2_that_does")
test_session_scope2.py import pytest def test_3_that_uses_all_fixtures(manually_session_resource, function_resource): print("test_2_that_does_not")
以äžãéå§ããŸãã
tmp\session scope>py.test -s -v
ãŸããPyTestã--fixtureså
¥åãã©ã¡ãŒã¿ãŒããµããŒãããåŒã³åºãããå Žåãconftest.pyïŒdocstringããã£ãïŒã§èª¬æãããŠãããã®ãå«ãã䜿çšå¯èœãªãã¹ãŠã®ãã£ã¯ã¹ãã£ãŒãè¿ããŸãã
tmp\session scope>py.test --fixtures
ãªã¯ãšã¹ããªããžã§ã¯ã
æ¡åŒµãã£ã¯ã¹ãã£ãäœæããäŸã§ã¯ããªã¯ãšã¹ããã©ã¡ãŒã¿ãæž¡ããŸããã ããã¯ãaddfinalizerã¡ãœãããéããŠãã¡ã€ãã©ã€ã¶ãŒã远å ããããã«è¡ãããŸããã ãã ãããã®ãªããžã§ã¯ãã«ã¯å€ãã®å±æ§ãšä»ã®ã¡ãœããïŒ
å
¬åŒAPIã®å®å
šãªãªã¹ãïŒããããŸãã
import pytest @pytest.fixture(scope="function") def resource_setup(request): print request.fixturename print request.scope print request.function.__name__ print request.cls print request.module.__name__ print request.fspath def test_1(resource_setup): assert True class TestClass(): def test_2(self, resource_setup): assert True
以äžãéå§ããŸãã
tmp>py.test -v -s request_object.py
ãã©ã¡ãŒã¿å
ãã©ã¡ãŒã¿åã¯ãç°ãªãäžé£ã®å
¥åãã©ã¡ãŒã¿ã䜿çšããŠåããã¹ããå®è¡ããæ¹æ³ã§ãã ããšãã°ãæååã5æåããé·ãå Žåã¯çå笊ãã5æåããçãå Žåã¯æå笊ããæååã«æ£ç¢ºã«5æåãããå Žåã¯ãããã远å ãã颿°ããããŸãã ãããã£ãŠã3ã€ã®ãã¹ããäœæãã代ããã«ã1ã€ã®ãã¹ããäœæã§ããŸãããç°ãªããã©ã¡ãŒã¿ãŒã§åŒã³åºããŸãã
ãã¹ãã®ãã©ã¡ãŒã¿ãŒãèšå®ããã«ã¯ã2ã€ã®æ¹æ³ããããŸãã
1ïŒå€ã®é
åãæž¡ããã£ã¯ã¹ãã£ã®paramsãã©ã¡ãŒã¿ãŒã®å€ãä»ããŠã
ã€ãŸãããã®å Žåã®ãã£ã¯ã¹ãã£ã¯ããã©ã¡ãŒã¿ãŒãæž¡ãã©ãããŒã§ãã ãããŠããããã¯äžèšã®ãªã¯ãšã¹ããªããžã§ã¯ãã®param屿§ãä»ããŠãã¹ãèªäœã«æž¡ãããŸãã
2ïŒãã³ã¬ãŒã¿ïŒã©ãã«ïŒ@ pytest.mark.parametrizeãä»ããŠã倿°åã®ãªã¹ããšãã®å€ã®é
åãæž¡ãããŸãã
ã ããæåã®æ¹æ³ã
import pytest def strange_string_func(str): if len(str) > 5: return str + "?" elif len(str) < 5: return str + "!" else: return str + "." @pytest.fixture(scope="function", params=[ ("abcdefg", "abcdefg?"), ("abc", "abc!"), ("abcde", "abcde.") ]) def param_test(request): return request.param def test_strange_string_func(param_test): (input, expected_output) = param_test result = strange_string_func(input) print "input: {0}, output: {1}, expected: {2}".format(input, result, expected_output) assert result == expected_output
以äžãéå§ããŸãã
tmp>py.test -s -v parametrizing_base.py
1ã€ã®äžå¿«ãªè©³çްãé€ãããã¹ãŠãæ£åžžã«æ©èœããŸãããã¹ãã®ååã«ãã£ãŠãã©ã®çš®é¡ã®ãã©ã¡ãŒã¿ãŒããã¹ãã«æž¡ãããããçè§£ããããšã¯äžå¯èœã§ãã ãããŠããã®å Žåããã£ã¯ã¹ãã£ãã©ã¡ãŒã¿IDã圹ç«ã¡ãŸãã ãã¹ãåã®ãªã¹ãïŒé·ãã¯ãã¹ãã®æ°ãšäžèŽããå¿
èŠããããŸãïŒããŸãã¯æçµåãçæãã颿°ã®ãããããåãå
¥ããŸãã
import pytest def strange_string_func(str): if len(str) > 5: return str + "?" elif len(str) < 5: return str + "!" else: return str + "." @pytest.fixture(scope="function", params=[ ("abcdefg", "abcdefg?"), ("abc", "abc!"), ("abcde", "abcde.")], ids=["len>5","len<5","len==5"] ) def param_test(request): return request.param def test_strange_string_func(param_test): (input, expected_output) = param_test result = strange_string_func(input) print "input: {0}, output: {1}, expected: {2}".format(input, result, expected_output) assert result == expected_output def idfn(val): return "params: {0}".format(str(val)) @pytest.fixture(scope="function", params=[ ("abcdefg", "abcdefg?"), ("abc", "abc!"), ("abcde", "abcde.")], ids=idfn ) def param_test_idfn(request): return request.param def test_strange_string_func_with_ifdn(param_test_idfn): (input, expected_output) = param_test result = strange_string_func(input) print "input: {0}, output: {1}, expected: {2}".format(input, result, expected_output) assert result == expected_output
以äžãéå§ããŸãã
tmp>py.test -s -v parametrizing_named.py --collect-only
ãã®å Žåã远å ãã©ã¡ãŒã¿ãŒâcollect-onlyãæå®ããŠPyTestãèµ·åããŸãããããã«ããããã©ã¡ãŒã¿ãŒåã«ãã£ãŠçæããããã¹ãŠã®ãã¹ããå®è¡ããã«åéã§ããŸãã
2çªç®ã®æ¹æ³ã«ã¯1ã€ã®å©ç¹ããããŸãïŒç°ãªããã©ã¡ãŒã¿ãŒã§è€æ°ã®ã©ãã«ãæå®ãããšããã¹ãŠã®å¯èœãªãã©ã¡ãŒã¿ãŒã»ããïŒã€ãŸãããã©ã¡ãŒã¿ãŒã®ãã«ã«ãç©ïŒã§ãã¹ããéå§ãããŸãã
import pytest @pytest.mark.parametrize("x", [1,2]) @pytest.mark.parametrize("y", [10,11]) def test_cross_params(x, y): print "x: {0}, y: {1}".format(x, y) assert True
以äžãéå§ããŸãã
tmp>py.test -s -v parametrizing_combinations.py
ãã©ã¡ãŒã¿ãŒåã©ãã«ã§ã¯ããã©ã¡ãŒã¿ãŒãèšå®ããæåã®æ¹æ³ãšåæ§ã«ãåºåã«ãã©ã¡ãŒã¿ãŒã衚瀺ããidsãã©ã¡ãŒã¿ãŒãæž¡ãããšãã§ããŸãã
import pytest def idfn_x(val): return "x=({0})".format(str(val)) def idfn_y(val): return "y=({0})".format(str(val)) @pytest.mark.parametrize("x", [-1,2], ids=idfn_x) @pytest.mark.parametrize("y", [-10,11], ids=idfn_y) def test_cross_params(x, y): print "x: {0}, y: {1}".format(x, y) assert True @pytest.mark.parametrize("x", [-1,2], ids=["negative x","positive y"]) @pytest.mark.parametrize("y", [-10,11], ids=["negative y","positive y"]) def test_cross_params_2(x, y): print "x: {0}, y: {1}".format(x, y) assert True
以äžãéå§ããŸãã
tmp>py.test -s -v parametrizing_combinations_named.py
è€æ°ã®ãã£ã¯ã¹ãã£ãšãã£ã¯ã¹ãã£ã䜿çšããŠãã£ã¯ã¹ãã£ãåŒã³åºããŸã
PyTestã¯ããã¹ãã®ããã«åŒã³åºããããã£ã¯ã¹ãã£ã®ãªã¹ããå¶éããŸããã
import pytest @pytest.fixture() def fixture1(request): print("fixture1") @pytest.fixture() def fixture2(request): print("fixture2") @pytest.fixture() def fixture3(request): print("fixture3") def test_1(fixture1, fixture2): print("test_1") def test_2(fixture1, fixture2, fixture3): print("test_2")
tmp>py.test -s -v multiply_fixtures.py
ãŸããã©ã®ãã£ã¯ã¹ãã£ãŒããããèªäœã«å¯ŸããŠä»»æã®æ°ã®ãã£ã¯ã¹ãã£ãŒã®å®è¡ãåŒã³åºãããšãã§ããŸãã
import pytest @pytest.fixture() def fixture1(request, fixture2): print("fixture1") @pytest.fixture() def fixture2(request, fixture3): print("fixture2") @pytest.fixture() def fixture3(request): print("fixture3") def test_1(fixture1): print("test_1") def test_2(fixture2): print("test_2")
tmp>py.test -s -v fixtures_use_fixtures.py
ã¿ã°
PyTestã¯ããããŒã¯ããšåŒã°ãã@ pytest.markãã³ã¬ãŒã¿ã®ã¯ã©ã¹ããµããŒãããŠããŸããåºæ¬ãªã¹ãã«ã¯ã次ã®ã©ãã«ãå«ãŸããŸãã1ïŒ@ pytest.mark.parametrize-ãã¹ãã®ãã©ã¡ãŒã¿ãŒåïŒäžèšïŒ2ïŒ@ pytest.mark.xfail-ãã¹ãã«åæ ŒããªãããšãããŒã¯ããPyTestã¯ãããæåŸ
ãããåäœãšããŠèªèããŸãïŒéçºãããæ©èœã®ãã¹ãã®ã¿ã€ã ã¹ã¿ã³ããšããŠæçšã§ãïŒããŸãããã®ã©ãã«ã¯ããã¹ãããã®ã©ãã«ã§ããŒã¯ãããæ¡ä»¶ãåãå
¥ããå ŽåããããŸãã3ïŒ@ pytest.mark.skipif-ãã¹ããã¹ããããããšãã®æ¡ä»¶ãèšå®ã§ããŸã;4ïŒ@ pytest.mark.usefixtures-ãã¹ãã®ããã«åŒã³åºããããã¹ãŠã®ãã£ã¯ã¹ãã£ããªã¹ãã§ããŸããäžè¬çã«ããªã¹ãã¯åºããã³ãã³ããpy.test-ããŒã«ãŒãã import pytest import sys @pytest.mark.xfail() def test_failed(): assert False @pytest.mark.xfail(sys.platform != "win64", reason="requires windows 64bit") def test_failed_for_not_win32_systems(): assert False @pytest.mark.skipif(sys.platform != "win64", reason="requires windows 64bit") def test_skipped_for_not_win64_systems(): assert False
以äžãéå§ããŸãã
tmp>py.test -s -v basic_marks.py
éèŠãªè¿œå æ©èœã¯ããŠãŒã¶ãŒãã©ãã«ãä»»æã«èšå®ã§ããããšã§ããããã«ãããã©ãã«åã§åå¥ã«å®è¡ãããã¹ãã¹ã€ãŒããéžæãã-mã¹ã€ããã§æž¡ãããšãã§ããŸãã import pytest def test_1(): print "test_1" @pytest.mark.critital_tests def test_2(): print "test_2" def test_3(): print "test_3"
tmp>py.test -s -v -m "critital_tests" custom_marks.py
ã©ãã«ã¯ãpytest.iniã¢ãžã¥ãŒã«ã®èª¬æã䜿çšããŠèª¬æãããã¹ãŠã®ã¢ãžã¥ãŒã«ã§äœ¿çšå¯èœã«ããããšãã§ããŸããåæã«ããpy.test --markersãã§ååŸããå©çšå¯èœãªã¿ã°ã®ãªã¹ãã«è¡šç€ºãããŸããpytest.ini
tmp>py.test --markers @pytest.mark.critical_test: mark test as critical. These tests must to be checked first. âŠ......
ãŸãããã¹ãã ãã§ãªããã¯ã©ã¹ãã¢ãžã¥ãŒã«ïŒã€ã³ããŒããããã¢ãžã¥ãŒã«ã®å±æ§ã倿ŽããŠèšå®ïŒããŸãã¯ãã©ã¡ãŒã¿ãŒåã«ãã£ãŠååŸããããã®èµ·åã«ãã©ãã«ãä»ããããšãã§ããŸãïŒæ¬¡ã®äŸãåç
§ïŒã import pytest pytestmark = pytest.mark.level1 def test_1(): print "test_1" @pytest.mark.level2 class TestClass: def test_2(self): print "test_2" @pytest.mark.level3 def test_3(self): print "test_3"
tmp>py.test -s -v -m "level3" custom_marks_others.py
tmp>py.test -s -v -m "level2" custom_marks_others.py
tmp>py.test -s -v -m "level1" custom_marks_others.py
import pytest @pytest.mark.parametrize(("x","expected"), [ (1,2), pytest.mark.critical((2,3)), (3,4) ]) def test_inc(x,expected): print x, "+ 1 = ", expected assert x + 1 == expected
tmp>py.test -s -v -m "critical" custom_marks_params.py
äŸå€åŠç
ãã¡ããããã¹ãçšã®æ¬æ Œçãªã¢ãžã¥ãŒã«ãšããŠãPyTestã§ã¯ãwith pytest.raisesïŒïŒãã䜿çšããŠãè¿ãããäŸå€ã®æ£ç¢ºãã確èªããããšãã§ããŸãã import pytest def f(): print 1/0 def test_exception(): with pytest.raises(ZeroDivisionError): f()
tmp>py.test -s -v check_exception.py
ååãŸãã¯IDã«ãããã¹ãã®å®è¡
module.py::class::method orã®åœ¢åŒã§ã¢ãžã¥ãŒã«ãžã®ãã«ãã¹ããªã¹ãããããšã«ãããã¢ãžã¥ãŒã«ããåã
ã®ãã¹ããå®è¡ã§ããŸããmodule.py::functionããŸããååã®äžéšã-kãã©ã°ã§æž¡ããŸãã import pytest def test_one(): print "test_one" def test_one_negative(): print "test_one_negative" def test_two(): print "test_one_negative"
tmp>py.test -s -v call_by_name_and_id.py::test_two
tmp>py.test -s -v -k "one" call_by_name_and_id.py
Eclipseã§ã®PyDevãšã®çµ±å
PyTestã¯ãEclipseã®PyDevã¢ãžã¥ãŒã«ã®PyUnitã³ã³ããŒãã³ãã«çµ±åãããŠããããšã«èšåããããšæããŸããèšå®ã§ã䜿çšããå¿
èŠãããããšãæå®ããå¿
èŠããããŸãã
远å ã¢ãžã¥ãŒã«
PyTestã«ã¯å€æ°ã®ã¢ããªã³ã¢ãžã¥ãŒã«ããããŸããèå³ã®ããã¢ãžã¥ãŒã«ãšãã®çç±ã®ã¿ã«èšåããããšãã§ããŸãïŒã¢ãžã¥ãŒã«ã®è©³çްã«ã€ããŠã¯ãäžèšã®ãªã³ã¯ãåç
§ããŠãã ããïŒïŒpytest-describe-å¥ã®ã¬ãã«ã®æœè±¡åã远å ããŸãïŒåçã®module-function-testcaseãšããŠmodule-description-functionïŒãpytest-instafail-ã¢ãžã¥ãŒã«ã®åºæ¬çãªåäœã倿ŽããŠãã»ãã·ã§ã³å
šäœã®çµããã§ã¯ãªããå®è¡äžã«ãã¹ãŠã®ãšã©ãŒãšã¯ã©ãã·ã¥ã衚瀺ãããããã«ããŸããpytest-marks-ãã¹ãã«è€æ°ã®ã©ãã«ãåæã«èšå®ã§ããŸãïŒ @pytest.mark.red @pytest.mark.green @pytest.mark.blue def some_test_method(self): .....
pytest-ordering -Runã©ãã«ã§ãã¹ããå®è¡ããé åºãæåã§èšå®ã§ããŸãã import pytest @pytest.mark.run(order=2) def test_foo(): assert True @pytest.mark.run(order=1) def test_bar(): assert True
pytest-pep8 -pep-8èŠçŽã«æºæ ããŠãããã©ãããã¹ãã³ãŒãã確èªã§ããŸããpytest-smartcov-å®å
šãŸãã¯éšåçãªãã¹ãã®ã³ãŒãã®ã«ãã¬ããžã確èªã§ããŸããpytest-timeout-ã³ãã³ãã©ã€ã³ãã©ã¡ãŒã¿ãŒãŸãã¯ç¹å¥ãªã©ãã«ã䜿çšããŠãã¿ã€ã ã¢ãŠãã§ãã¹ããå®äºã§ããŸããpytest-sugar -PyTestã®åºåã®å€èгã倿Žããé²è¡ç¶æ³ããŒãšå®äºçã远å ã§ããŸããããã¯å Žæã«ããããããçŸããèŠããããŸãæçã§ã¯ãããŸãããããšãã
PyTestã®åºæ¬çãªããã¥ã¡ã³ãã«ã¯ããã®æ¡åŒµããã䜿çšã«é¢ããå€ãã®è峿·±ãäŸãèšèŒãããŠããŸããããããæ¬¡åã¯ãããã«ã€ããŠã話ããããšæããŸãïŒåºæ¬çãªPyTestã®åäœã®ç®¡çïŒãã¹ãã®åéã«äœ¿çšããããã³ãã¬ãŒããã³ãã³ãã©ã€ã³ã®é«åºŠãªãªãã·ã§ã³ã®è¿œå ïŒããã©ã¡ãŒã¿ãŒåäžã®ãã¹ãã®åéããã»ã¹ã®å¶åŸ¡ïŒmetafuncãªããžã§ã¯ãïŒãªã©ã