一. 測試模塊內部使用fixture和測試模塊調用外部公共的fixture
1. unittest框架下的測試用例模塊
from selenium import webdriver import unittest from PageObjects.login_page import LoginPage from PageObjects.index_page import IndexPage from TestDatas.login_testdatas import * from TestDatas.CommonData import * import time class TestLogin(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome() self.driver.get(common_url) self.driver.maximize_window() #用戶名密碼正確 def test_login_success(self): LoginPage(self.driver).login(login_success_data["username"], login_success_data["passwd"]) nickName = IndexPage(self.driver).get_nickName() self.assertEqual("我的帳戶[小蜜蜂96027]", nickName) def tearDown(self): time.sleep(2) self.driver.quit()
2. 測試用例模塊內部使用fixture
fixture:即測試用例執行的環境准備和清理,在unittest中即指setup()、teardown()
from selenium import webdriver import unittest from PageObjects.login_page import LoginPage from PageObjects.index_page import IndexPage from TestDatas.login_testdatas import * from TestDatas.CommonData import * import time import pytest class TestLogin: @pytest.fixture def init_driver(self): self.driver = webdriver.Chrome() self.driver.get(common_url) self.driver.maximize_window() yield self.driver time.sleep(2) self.driver.quit() #用戶名密碼正確 def test_login_success(self, init_driver): LoginPage(init_driver).login(login_success_data["username"], login_success_data["passwd"]) nickName = IndexPage(init_driver).get_nickName() assert "我的帳戶[小蜜蜂96027]" == nickName
3. 測試用例模塊調用外部公共的fixture
有時,多個測試用例模塊要使用同一fixture,如果在每個模塊內部都定義一遍fixture則略顯麻煩,pytest提供了conftest.py文件,用來定義公共的fixture,多個測試模塊都可以調用,運行測試用例時,不需要導入這個文件,它會自動查找conftest.py文件,然后去找到對應的fixture
在測試用例模塊的同級目錄下創建一個conftest.py文件
from selenium import webdriver from TestDatas.CommonData import * import pytest import time @pytest.fixture def init_driver(): driver = webdriver.Chrome() driver.get(common_url) driver.maximize_window() yield driver time.sleep(2) driver.quit()
測試用例模塊test_login.py調用外部公共的fixture
from selenium import webdriver import unittest from PageObjects.login_page import LoginPage from PageObjects.index_page import IndexPage from TestDatas.login_testdatas import * from TestDatas.CommonData import * import time import pytest class TestLogin: #用戶名密碼正確 @pytest.mark.usefixtures("init_driver") def test_login_success(self, init_driver): LoginPage(init_driver).login(login_success_data["username"], login_success_data["passwd"]) nickName = IndexPage(init_driver).get_nickName() assert "我的帳戶[小蜜蜂96027]" == nickName
4. 比較
pytest和unittest相比:
1. 需要import pytest
2. 不再需要unittest.TestCase
3. 如果在內部使用fixture,則函數只需要傳參,參數為被@pytest.fixture裝飾的函數名init_driver(init_driver=init_driver());如果調用外部公共的fixture,除了傳參之外,還要在測試用例類或函數前面加上一句:@pytest.mark.usefixtures("init_driver")
4. fixture函數中以yield分割環境准備和環境清理,且需要返回self.driver或driver
5. 斷言方式有所改變,unittest采用self.assertEqual或其他,pytest采用assert 表達式
二. 裝飾器函數fixture的作用域默認是function,且autouse=False
@pytest.fixture中的fixture函數源碼如下
四大作用域:
function:每個test都運行,默認是function的scope,即unittest中的setUp和tearDown
class:每個class的所有test只運行一次。即unittest中的setUpClass和tearDownClass
module:每個module的所有test只運行一次(分類里和類外)
session:每個session只運行一次(如連接數據庫操作)
值得注意的是默認的autouse=False,所以函數需要使用對應的fixture時,需要添加@pytest.mark.usefixtures("init_driver"),並且將被fixture裝飾的函數名init_driver作為參數,傳給測試用例函數,如果autouse=True,那么會自動給每個測試用例添加fixture,而init_driver這樣的環境准備和清理工作並非每個測試用例都需要,所以autouse一般采用默認值False
三. pytest收集測試用例的規則
1. 默認從當前目錄中搜集測試用例,即在哪個目錄下運行pytest命令,則從哪個目錄當中搜索
2. 搜索規則:
1) 符合命令規則test_*.py 或者 *_test.py 的文件
2) 以test_開頭的函數名
3) 以Test開頭的測試類 (沒有__init__函數) 當中,以test_開頭的函數
當前目錄下(D:\python_workshop\WEB_framework)有兩個測試用例模塊,test_login.py和test_invest.py,前者測試用例類TestLogin中有四個測試用例,另外還在測試用例類外添加了一個test_demo函數,后者有四個測試用例,這九個測試用例中我只在用戶名為空的用例上打了smoke標記
在調用pytest -m smoke運行時,發現9條用例被找到了,但8條沒有被選擇,只選擇了打了標記的
參考文章
http://www.cnblogs.com/cnhkzyy/p/9270830.html