python pytest測試框架(一)


本文鏈接:https://blog.csdn.net/yxxxiao/article/details/94591174
目錄

一、安裝

二、第一個測試例子

三、pytest參數

  1、-K EXPRESSION

  3、--maxfail=num

  4、-m MARKEXPR

  5、 -v, --verbose

  6、-q, --quiet

  7、--junit-xml=path

  8、 --result-log=path

四、pytest 用例規則

五、pytest運行方式

  1.單獨執行某一個py文件里所有的用例

  2.執行目錄下所有用例

  3.單獨執行某個用例

六、fixture

  1、fixture scope的范圍參數

  2、調用fixture的三種方法

    2.1函數或類里面方法直接傳fixture的函數參數名稱

    2.2使用裝飾器@pytest.mark.usefixtures()修飾需要運行的用例

    2.3疊加usefixtures

  3.usefixtures與傳fixture區別

  4.fixture自動使用autouse=True

  5.conftest.py的作用范圍

    5.1conftest在不同的層級間的作用域不一樣

    5.2conftest是不能跨模塊調用的(這里沒有使用模塊調用)

一、安裝
pytest不是python默認的package,需要手動安裝。

pytest支持python 2.6--3.5之間的版本,同時可以在windows、unix系統上安裝

安裝方式:

pip install pytest
安裝完成后,可以查看版本:

pytest --version


二、第一個測試例子
1.創建test_sample.py文件,創建一個方法、一個用例

# content of test_sample.py
def func(x):
  return x + 1
def test_answer():   assert func(3) == 5

 

2.執行

$ pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 1 item

test_sample.py F [100%]

================================= FAILURES =================================
_______________________________ test_answer ________________________________

def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)

test_sample.py:5: AssertionError
========================= 1 failed in 0.12 seconds =========================

 

此測試返回失敗報告,因為func(3)不返回5。

三、pytest參數
1、-K EXPRESSION
執行某個關鍵字的用例
用例要匹配給出的表達式;使用python的語法,匹配的范圍是文件名、類名、函數名為變量,用and來區分

如下面一段測試用例

# content of test.py
class TestClass(object):
def test_zne(self):
x = "this"
assert 'h' in x


def test_two(self):
x = "hello"
assert hasattr(x, 'check')

def test_a(self):
assert 1==2


運行pytest時帶-k參數

pytest -k "test and TestClass and not test_a" test.py

結果如下:

 

可以看出,test_a這個用例被取消選擇了,沒有運行了

3、--maxfail=num
當錯誤個數到達給定數時,退出測試,這里就不列舉實例了,結果與-x類似

4、-m MARKEXPR
  只能運行有相應標識的測試用例,使用這個參數,測試用例要使用@pytest.mark.marker修飾

  如下實例

# content of test.py
import pytest
class TestClass(object):
  def test_one(self):
    '''new_etests'''
    x = "this"
    assert 'h' in x

  @pytest.mark.slow
  def test_two(self):
    '''new_sssetests'''
    x = "hello"
    assert hasattr(x, 'check')

  def test_a(self):
    assert 1==2

teste_two使用了@pytest.mark.slow來修飾

在使用時,使用如下參數

pytest –m slow test.py

結果如下:

 

從上圖中可以看出,只運行了一個我們帶有標識的用例。

注意,-m后面不能帶''號(單引號),只能帶“”(雙引號),不然識別不到

如果要運行多個標識的話,用表達式,如下

pytest -m "slow or faster" 運行有slow標識或 faster標識用例
pytest -m "slow and faster" 運行有slow和faster標識的用例
pytest -m "slow and not faster" 運行有slow和沒有faster標識的用例

5、 -v, --verbose
詳細結果

6、-q, --quiet
 極簡結果顯示,簡化控制台的輸出,可以看出輸出信息和之前不添加-q不信息不一樣, 下圖中有兩個..點代替了pass結果

7、-s
輸入我們用例中的調式信息,比如print的打印信息等,我們在用例中加上一句 print(driver.title),我們再運行一下我們的用例看看,調試信息輸出

8、-V
可以輸出用例更加詳細的執行信息,比如用例所在的文件及用例名稱等

9、--junit-xml=path
輸出xml文件格式,在與jenkins做集成時使用

10、 --result-log=path
將最后的結果保存到本地文件中

注意:標黃的是經常使用的

四、pytest 用例規則
pytest可以在不同的函數、包中發現用例,發現的規則如下

文件名以test_開頭的py文件
以test_開頭的函數
以Test開頭的類
以test_開頭的方法(與2類似)
要注意的是所有的包必須要有init.py文件(在使用各種編輯器時會自動生成)
五、pytest運行方式
1.單獨執行某一個py文件里所有的用例

pytest test.py

2.執行目錄下所有用例

pytest testcase/

3.單獨執行某個用例
以函數形式的用例

pytest test_login.py::test_1

以類形式的用例

pytest test_login.py::TestClass::test_1

六、pytest fixture
pytest支持以xUnit格式型的測試模型(setup/teardown),但還與python自帶的unittest還是有一點差別,如下

  模塊形式----使用setup_module/teardown_module  
  函數形式----使用setup_function/teardown_function
  類形式----使用setup_class/teardown_class
  方法形式---使用setup_method/teardown_method
注意:

1.pytest也可以直接運行unittest模式的測試用例

2.如果你在pytest模式中使用setupClass()函數是不行的,不會識別,但如果用例類繼承之unittest.Testcase,還是可以識別的

1、fixture scope的范圍參數
之前使用@pytest.fixture(scope='module')來定義框架,scope的參數有以下幾種

  function   每一個用例都執行
  class        每個類執行
  module     每個模塊執行(函數形式的用例)
  session     每個session只運行一次,在自動化測試時,登錄步驟可以使用該session
2、調用fixture的三種方法
2.1函數或類里面方法直接傳fixture的函數參數名稱

from __future__ import print_function
import pytest

@pytest.fixture(scope='module')
def resource_a_setup(request):
  print('\nresources_a_setup()')
  def resource_a_teardown():
    print('\nresources_a_teardown()')
  request.addfinalizer(resource_a_teardown)

def test_1(resource_a_setup):
  print('test_1()')

def test_2():
  print('\ntest_2()')

def test_3(resource_a_setup):
  print('\ntest_3()')

 


使用-s -v運行查看詳情如下

 

2.2使用裝飾器@pytest.mark.usefixtures()修飾需要運行的用例

import pytest
# test_fixture1.py


@pytest.fixture()
def test1():
  print('\n開始執行function')


@pytest.mark.usefixtures('test1')
def test_a():
  print('---用例a執行---')


@pytest.mark.usefixtures('test1')
class TestCase:

  def test_b(self):
    print('---用例b執行---')

  def test_c(self):
    print('---用例c執行---')


if __name__ == '__main__':
  pytest.main(['-s', 'test_fixture1.py'])

 


輸出結果:

platform win32 -- Python 3.7.0, pytest-4.0.2, py-1.7.0, pluggy-0.8.0
rootdir: C:\Program Files\PycharmProjects\exercise, inifile:collected 3 items

test_fixture1.py 
開始執行function
.---用例a執行---

開始執行function
.---用例b執行---

開始執行function
.---用例c執行---
[100%]

========================== 3 passed in 0.06 seconds ===========================
Process finished with exit code 0

 


2.3疊加usefixtures
如果一個方法或者一個class用例想要同時調用多個fixture,可以使用@pytest.mark.usefixture()進行疊加。注意疊加順序,先執行的放底層,后執行的放上層

import pytest
# test_fixture1.py


@pytest.fixture()
def test1():
  print('\n開始執行function1')


@pytest.fixture()
def test2():
  print('\n開始執行function2')


@pytest.mark.usefixtures('test1')
@pytest.mark.usefixtures('test2')
def test_a():
  print('---用例a執行---')


@pytest.mark.usefixtures('test2')
@pytest.mark.usefixtures('test1')
class TestCase:

  def test_b(self):
    print('---用例b執行---')

  def test_c(self):
    print('---用例c執行---')
    

if __name__ == '__main__':
  pytest.main(['-s', 'test_fixture1.py'])

輸出結果:

============================= test session starts =============================
platform win32 -- Python 3.7.0, pytest-4.0.2, py-1.7.0, pluggy-0.8.0
rootdir: C:\Program Files\PycharmProjects\exercise, inifile:collected 3 items

test_fixture1.py 
開始執行function2

開始執行function1
.---用例a執行---

開始執行function1

開始執行function2
.---用例b執行---

開始執行function1

開始執行function2
.---用例c執行---
[100%]

========================== 3 passed in 0.03 seconds ===========================
Process finished with exit code 0

3.usefixtures與傳fixture區別
 如果fixture有返回值,那么usefixture就無法獲取到返回值,這個是裝飾器usefixture與用例直接傳fixture參數的區別。

當fixture需要用到return出來的參數時,只能講參數名稱直接當參數傳入,不需要用到return出來的參數時,兩種方式都可以。

4.fixture自動使用autouse=True
當用例很多的時候,每次都傳這個參數,會很麻煩。fixture里面有個參數autouse,默認是False沒開啟的,可以設置為True開啟自動使用fixture功能,這樣用例就不用每次都去傳參了

autouse設置為True,自動調用fixture功能

import pytest
# test_fixture1.py


@pytest.fixture(scope='module', autouse=True)
def test1():
  print('\n開始執行module')


@pytest.fixture(scope='class', autouse=True)
def test2():
  print('\n開始執行class')


@pytest.fixture(scope='function', autouse=True)
def test3():
  print('\n開始執行function')


def test_a():
  print('---用例a執行---')


def test_d():
  print('---用例d執行---')


class TestCase:

  def test_b(self):
    print('---用例b執行---')

  def test_c(self):
    print('---用例c執行---')


if __name__ == '__main__':
  pytest.main(['-s', 'test_fixture1.py'])

輸出結果:

============================= test session starts =============================
platform win32 -- Python 3.7.0, pytest-4.0.2, py-1.7.0, pluggy-0.8.0
rootdir: C:\Program Files\PycharmProjects\exercise, inifile:collected 4 items

test_fixture1.py 
開始執行module

開始執行class

開始執行function
.---用例a執行---

開始執行class

開始執行function
.---用例d執行---

開始執行class

開始執行function
.---用例b執行---

開始執行function
.---用例c執行---

5.conftest.py的作用范圍
一個工程下可以建多個conftest.py的文件,一般在工程根目錄下設置的conftest文件起到全局作用。在不同子目錄下也可以放conftest.py的文件,作用范圍只能在改層級以及以下目錄生效。

項目實例:

目錄結構:

 

5.1conftest在不同的層級間的作用域不一樣

# conftest層級展示/conftest.py

import pytest

@pytest.fixture(scope='session', autouse=True)
def login():
  print('----准備登錄----')
# conftest層級展示/sougou_login/conftest
import pytest
 
 
@pytest.fixture(scope='session', autouse=True)
def bai_du():
    print('-----登錄百度頁面-----')
# conftest層級展示/sougou_login/login_website
import pytest
 
 
class TestCase:
    def test_login(self):
        print('hhh,成功登錄百度')
 
 
if __name__ == '__main__':
    pytest.main(['-s', 'login_website.py'])

輸出結果:

============================= test session starts =============================
platform win32 -- Python 3.7.0, pytest-4.0.2, py-1.7.0, pluggy-0.8.0
rootdir: C:\Program Files\PycharmProjects\conftest層級演示\sougou_login, inifile:collected 1 item

login_website.py ----准備登錄----
-----登錄百度頁面-----
.hhh,成功登錄百度
[100%]

========================== 1 passed in 0.03 seconds ===========================
Process finished with exit code 0

5.2conftest是不能跨模塊調用的(這里沒有使用模塊調用)

# conftest層級演示/log/contfest.py
import pytest

@pytest.fixture(scope='function', autouse=True)
def log_web():
    print('打印頁面日志成功')

# conftest層級演示/log/log_website.py

import pytest

def test_web():
  print('hhh,成功一次打印日志')

def test_web1():
  rint('hhh,成功兩次打印日志')


if __name__ == '__main__':
  pytest.main(['-s', 'log_website.py'])

輸出結果:

============================= test session starts =============================
platform win32 -- Python 3.7.0, pytest-4.0.2, py-1.7.0, pluggy-0.8.0
rootdir: C:\Program Files\PycharmProjects\conftest層級演示\log, inifile:
collected 2 items

log_website.py ----准備登錄----
打印頁面日志成功
hhh,成功一次打印日志
.打印頁面日志成功
hhh,成功兩次打印日志
.

========================== 2 passed in 0.02 seconds ===========================


免責聲明!

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



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