pytest學習筆記(二)


繼續文檔的第二章

(一)pytest中可以在命令行中靜態/動態添加option,這里沒什么好講的,略過...

        這里面主要講下如何試用skip/xfail,還有incremental(包含一些列的測試步驟,如果某一步出錯后,該步驟之后的所有步驟都沒有任何意義了,xfail掉)

1)首先來看下怎樣通過命令行來skip一些case,首先要添加個option,然后使用@pytest.mark.skipif( condition) , xfail使用@pytest.mark.xfail( condition,reson,run,raise),這里不詳細介紹了

 

import pytest
def test_func_fast():
    print 'fast'
@pytest.mark.skipif(not pytest.config.getoption("--runslow"))
def test_func_slow_1():
    print 'skip slow'
@pytest.mark.xfail(not pytest.config.getoption("--runslow"))
def test_func_slow_2():
    print 'xfail slow'

2)然后來看下如何實現incremental,首先在測試文件的目錄下創建conftest.py, 代碼如下:

# content of conftest.py

import pytest

def pytest_runtest_makereport(item, call):
    if "incremental" in item.keywords:
        if call.excinfo is not None:
            parent = item.parent
            parent._previousfailed = item

def pytest_runtest_setup(item):
    if "incremental" in item.keywords:
        previousfailed = getattr(item.parent, "_previousfailed", None)
        if previousfailed is not None:
            pytest.xfail("previous test failed (%s)" %previousfailed.name)

然后創建test_steps.py

# content of test_step.py
import pytest

@pytest.mark.incremental
class TestUserHandling:
    def test_login(self, fix_err):
        pass
    def test_modification(self):
        assert 0
    def test_deletion(self):
        pass
def test_normal():
    assert 0

執行結果,在test_modification后的test_deletion 執行為x

3)由於pytest中的Error也划分到Fail中,而Unittest中是單獨講Error獨立出來,說明由於case中存在異常或錯誤導致case未能正常運行,其實在pytest中也可以做到這樣,只需要加上一點兒代碼,如下:

# content of test_step.py
import pytest

@pytest.fixture def fix_err(x): raise x

@pytest.mark.incremental
class TestUserHandling:
    def test_modification(self):
        pass
    def test_login(self, fix_err):
        try:
            raise RuntimeError("error")
        except AssertionError,e:
            pass
        except:
            fix_err(e)
    def test_deletion(self):
        pass
def test_normal():
    assert 0

其執行效果如下:

(二)、這里講下關於fixture,fixture是pytest特有的功能,它用pytest.fixture標識,定義在函數前面。在你編寫測試函數的時候,你可以將此函數名稱做為傳入參數,pytest將會以依賴注入方式,將該函數的返回值作為測試函數的傳入參數。例如上面的例子fix_err.

1)准備函數usefixtures

@pytest.fixture()
def cleandir():
    newpath = tempfile.mkdtemp()
    os.chdir(newpath)

@pytest.mark.usefixtures("cleandir")
class TestDirectoryInit:
    def test_cwd_starts_empty(self):
        assert os.listdir(os.getcwd()) == []
        with open("myfile", "w") as f:
            f.write("hello")

2)銷毀函數addfinalizer

@pytest.fixture()
def smtp(request):
    smtp = smtplib.SMTP("smtp.gmail.com")
    def fin():
        print ("teardown smtp")
        smtp.close()
    request.addfinalizer(fin)
    return smtp  # provide the fixture value

獲取調用函數信息: request 使用fixture標記函數后,函數將默認接入一個request參數,它將包含使用該fixture函數的函數信息

3)fixture的參數,有時我們需要全面測試多種不同條件下的一個對象,功能是否符合預期。我們可以通過params參數來指定傳入的參數。

class SMTP:
    def __init__(self, smtp, sender, receiver):
        self.smtp = smtp
        self.sender = sender
        self.receiver = receiver
    def __del__(self):
        self.smtp.close()

@pytest.fixture(params=[["smtp.gmail.com", "from@domain.com", "to@doamin.com"], ["mail.python.org", "from@python.org", "to@python.org"])
def smtp(request):
    return SMTP(#param)

def test_mail(smtp):
    message = "hello"
    assert smtp.sendmail(message)

4)fixture的作用域:function、module、session ,autouse=True使得函數將默認執行

work_dir = "/tmp/app"
@pytest.fixture(session="session", autouse=True)
def clean_workdir():
    shutil.rmtree(work_dir)
    os.mkdir(work_dir)
    os.chrdir(work_dir)

fixture的存在使得我們在編寫測試函數的准備函數、銷毀函數或者多個條件的測試提供了更加靈活的選擇。py.test --fixtures 可以查看所有的fixtures,包含目錄下及子目錄下的conftest.py

pytest.hookimpl這個沒太看明白,應該就是個鈎子函數,以后弄明白了再說,今天就到這兒了,下一節再說這個參數化的問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM