1. 程式人生 > >pytest 多個PY檔案執行時共享變數及用fixture和conftest

pytest 多個PY檔案執行時共享變數及用fixture和conftest

 

1.pytest需要測試多個py檔案,這些檔案有一定的依賴關係,同時執行的時候,需要只執行一次初始化setup,結束再執行一次teardown;

2.多個py檔案需要使用pytest的conftest.py,這個檔名是固定的,在同級目錄還需要__init__.py;

3.由於setup這種經典的初始化方法只支援module,class.method,function,setup

  module: 一個py檔案只執行一次,裡面可以是class和function;

  class: 每個class執行一次;

  method: class裡面的每個函式執行一次;

  function : 每個函式執行一次(函式不在class中);

  setup: 最小層級,每個函式執行一次;在allure報告中,現在在Test body中;其他級別顯示在的setup中;

4.經典初始化不支援多個py初始化,只能選用fixture;

  scope值 :預設是function;

  session 多個py檔案;

  module 一個py檔案裡面多個class或function;

  class: class級別;

  function:函式級別;

       由於我們是多個py所以,只能選擇session;

       yield 是setup和teardown分界線;

@pytest.fixture(scope="session")
def start_up_session():
    try:
        
        case_name = os.path.basename(__file__).replace('.py', '')
        print(case_name + " start")
        # yield 前面的是tearup的操作
        yield case_name
        # yield 後面的是teardown的操作
        print(case_name + " finish")

 

 

  autouse = True   fixture裡面有個引數autouse,預設是Fasle沒開啟的,可以設定為True開啟自動使用fixture功能,這樣用例就不用每次都去傳參了;

 

@pytest.fixture(scope="function", autouse=True)
def get_status():
    case_name = os.path.basename(os.path.abspath(__file__)).replace(".py", "")
    print(case_name + " begin")
    yield 1 if case_name.isalnum() else 0
    print(case_name + " finish")

# 不傳引數get_tstus也會執行 def test_1(): print(1111) def test_name(): print(2222) if __name__ == "__mian__": pytest.main(["-s", "test_base.py"]) ========================================= ============================= test session starts ============================= platform win32 -- Python 3.6.8, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Program Files\Python36\python.exe cachedir: .pytest_cache metadata: {'Python': '3.6.8', 'Platform': 'Windows-10-10.0.18362-SP0', 'Packages': {'pytest': '5.4.2', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'allure-pytest': '2.8.13', 'cov': '2.8.1', 'forked': '1.1.3', 'html': '2.1.1', 'metadata': '1.9.0', 'ordering': '0.6', 'rerunfailures': '9.0', 'timeout': '1.3.4', 'xdist': '1.32.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_202'} rootdir: F:\ShenjuCloudTest\APP plugins: allure-pytest-2.8.13, cov-2.8.1, forked-1.1.3, html-2.1.1, metadata-1.9.0, ordering-0.6, rerunfailures-9.0, timeout-1.3.4, xdist-1.32.0 collecting ... collected 2 items test_base.py::test_1 test_base begin PASSED [ 50%]1111 test_base finish test_base.py::test_name test_base begin PASSED [100%]2222 test_base finish ============================== 2 passed in 0.03s ============================== Process finished with exit code 0

 

 autouse = True   fixture裡面有個引數autouse,預設是Fasle沒開啟的,需要顯示呼叫;

import pytest
import os

# 預設autouse=Fasle
@pytest.fixture(scope="function")
def get_status():
    case_name = os.path.basename(os.path.abspath(__file__)).replace(".py", "")
    print(case_name + " begin")
    yield 1 if case_name.isalnum() else 0
    print(case_name + " finish")

# 顯式呼叫
@pytest.mark.usefixtures("get_status")
def test_1():
    print(1111)

# 顯式呼叫
@pytest.mark.usefixtures("get_status")
def test_name():
    print(2222)


if __name__ == "__mian__":
    pytest.main(["-s", "test_base.py"])

 

5.fixture 需要返回值:用傳引數呼叫:在函式引數中,插入fixture的引數;

import pytest
import os


@pytest.fixture(scope="function", autouse=True)
def get_status():
    case_name = os.path.basename(os.path.abspath(__file__)).replace(".py", "")
    print(case_name + " begin")
    yield 1 if case_name.isalnum() else 0
    print(case_name + " finish")


def test_1(get_status):
    num = get_status
    assert num == 0
    print(1111)


def test_name(get_status):
    num = get_status
    assert num < 1
    print(2222)


if __name__ == "__mian__":
    pytest.main(["-s", "test_base.py"])
===================================

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Program Files\Python36\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.6.8', 'Platform': 'Windows-10-10.0.18362-SP0', 'Packages': {'pytest': '5.4.2', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'allure-pytest': '2.8.13', 'cov': '2.8.1', 'forked': '1.1.3', 'html': '2.1.1', 'metadata': '1.9.0', 'ordering': '0.6', 'rerunfailures': '9.0', 'timeout': '1.3.4', 'xdist': '1.32.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_202'}
rootdir: F:\ShenjuCloudTest\APP
plugins: allure-pytest-2.8.13, cov-2.8.1, forked-1.1.3, html-2.1.1, metadata-1.9.0, ordering-0.6, rerunfailures-9.0, timeout-1.3.4, xdist-1.32.0
collecting ... collected 2 items

test_base.py::test_1 test_base begin
PASSED                                              [ 50%]1111
test_base finish

test_base.py::test_name test_base begin
PASSED                                           [100%]2222
test_base finish

6.fixture 不需要返回值:除了用傳引數呼叫,還可以用@pytest.mark.usefixtures();對class和函式都可以使用,記得和scope搭配;

import pytest
import os


@pytest.fixture(scope="function", autouse=True)
def get_status():
    case_name = os.path.basename(os.path.abspath(__file__)).replace(".py", "")
    print(case_name + " begin")
    yield 1 if case_name.isalnum() else 0
    print(case_name + " finish")

@pytest.mark.usefixtures("get_status")
def test_1():
    print(1111)

@pytest.mark.usefixtures("get_status")
def test_name():
    print(2222)


if __name__ == "__mian__":
    pytest.main(["-s", "test_base.py"])
=======================================
============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Program Files\Python36\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.6.8', 'Platform': 'Windows-10-10.0.18362-SP0', 'Packages': {'pytest': '5.4.2', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'allure-pytest': '2.8.13', 'cov': '2.8.1', 'forked': '1.1.3', 'html': '2.1.1', 'metadata': '1.9.0', 'ordering': '0.6', 'rerunfailures': '9.0', 'timeout': '1.3.4', 'xdist': '1.32.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_202'}
rootdir: F:\ShenjuCloudTest\APP
plugins: allure-pytest-2.8.13, cov-2.8.1, forked-1.1.3, html-2.1.1, metadata-1.9.0, ordering-0.6, rerunfailures-9.0, timeout-1.3.4, xdist-1.32.0
collecting ... collected 2 items

test_base.py::test_1 test_base begin
PASSED                                              [ 50%]1111
test_base finish

test_base.py::test_name test_base begin
PASSED                                           [100%]2222
test_base finish

 7. 多個py檔案使用conftest.py,名字固定,不要改;

  同級需要有__init__.py;

  千萬不要通過import匯入conftest,否則每個py檔案都會執行一遍conftest.py, 無法起到多個py只執行一次作用;pytest執行的時候自動去讀conftest.py配置;

 

 

 

 

import pytest
import os

# conftest.py

@pytest.fixture(scope="session")
def get_status():
    case_name = os.path.basename(os.path.abspath(__file__)).replace(".py", "")
    print(case_name + " begin")
    yield 1 if case_name.isalnum() else 0
    print(case_name + " finish")
import pytest
import os

# test_base 不傳引數,不要返回值

@pytest.mark.usefixtures("get_status")
def test_1():
    print(1111)


@pytest.mark.usefixtures("get_status")
def test_name():
    print(2222)


if __name__ == "__mian__":
    pytest.main(["-s", "test_base.py"])
====================================================================

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Program Files\Python36\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.6.8', 'Platform': 'Windows-10-10.0.18362-SP0', 'Packages': {'pytest': '5.4.2', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'allure-pytest': '2.8.13', 'cov': '2.8.1', 'forked': '1.1.3', 'html': '2.1.1', 'metadata': '1.9.0', 'ordering': '0.6', 'rerunfailures': '9.0', 'timeout': '1.3.4', 'xdist': '1.32.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_202'}
rootdir: F:\ShenjuCloudTest\APP
plugins: allure-pytest-2.8.13, cov-2.8.1, forked-1.1.3, html-2.1.1, metadata-1.9.0, ordering-0.6, rerunfailures-9.0, timeout-1.3.4, xdist-1.32.0
collecting ... collected 2 items

test/test_base.py::test_1 conftest begin
PASSED [ 50%]1111

test/test_base.py::test_name PASSED [100%]2222
conftest finish


============================== 2 passed in 0.03s ==============================

Process finished with exit code 0

import pytest
import os

# test_base1 傳引數,需要返回值;
def test_1(get_status):
    print("test_1" + str(get_status))
    print(1111)


def test_name(get_status):
    print("test_name" + str(get_status))
    print(2222)


if __name__ == "__mian__":
    pytest.main(["-s", "test_base.py"])
==========================================
============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Program Files\Python36\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.6.8', 'Platform': 'Windows-10-10.0.18362-SP0', 'Packages': {'pytest': '5.4.2', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'allure-pytest': '2.8.13', 'cov': '2.8.1', 'forked': '1.1.3', 'html': '2.1.1', 'metadata': '1.9.0', 'ordering': '0.6', 'rerunfailures': '9.0', 'timeout': '1.3.4', 'xdist': '1.32.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_202'}
rootdir: F:\ShenjuCloudTest\APP\test
plugins: allure-pytest-2.8.13, cov-2.8.1, forked-1.1.3, html-2.1.1, metadata-1.9.0, ordering-0.6, rerunfailures-9.0, timeout-1.3.4, xdist-1.32.0
collecting ... collected 2 items

test_base1.py::test_1 conftest begin
PASSED                                             [ 50%]test_11
1111

test_base1.py::test_name PASSED                                          [100%]test_name1
2222
conftest finish


============================== 2 passed in 0.05s ==============================

&n