https://zhuanlan.zhihu.com/p/161705540
文章总览图

fixture和unittest是冲突的。舍弃unittest只用pytest。
会遇到在很多用例当中,它的前置条件是长得一样的。用例写的越来越多的时候,肯定会遇到前置条件都差不多,大家差距不是很大。这样的话,如果每个py文件都写个setUp和tearDown,就重复率挺高的。要是能拎取出来做个公共的就好了。
实际上在unittest这个模式下,也可以做个公共的setUpClass,单独创建一个文件,然后引用下,继承一下,就变成公用的了。想做也是可以做的,但是pytest做的更好。fixture在项目当中作为公共用法来用。可以专门定义额外的setUp和tearDown,在单独的地方,不放在测试用例当中。测试用例将它主动引进来,作为它的前置和后置就好了。
首先定义fixture,怎么定义呢?
它是一个函数,只不过这个函数,我们要加上一个装饰说明,说明这个函数是有特殊用途的。什么特殊用途呢?
是作为我们的前置和后置。
那这个装饰器就是@pytest.fixture,在函数名称前面。
在pytest中,环境准备和环境清理是完全放在一起的。在unittest中,它是两个都分开的,一个是setUp,一个是tearDown,我们会定义两个函数。
在pytest中,只要一个函数就可以了。fixture可以在当前的文件中来定义,也可以额外得去定义。
第一种,公有化的方式:
前置和后置定义在特殊的文件当中,以后谁想要用,就直接调用就好了。一般调用函数,需要引进来才能调用,但是在pytest当中不需要。直接用个装饰器引用下就可以了,完全不需要引用这个文件。
1.它是怎么实现这种公有化的方式呢?
在TeatCase目录下,新建一个Python文件,文件名固定是:conftest。
这个文件就是个公有化的文件。conftest文件必须和测试用例放在一起,和测试用例文件是同级。fixture是一个函数。
可以看到源码解析:
def fixture(callable_or_scope=None,*args,scope="function",params=None,autouse=False,ids=None,name=None):"""Decorator to mark a fixture factory function.This decorator can be used, with or without parameters, to define afixture function.The name of the fixture function can later be referenced to cause itsinvocation ahead of running tests: testmodules or classes can use the ``pytest.mark.usefixtures(fixturename)``
可以看到第一个参数是scope,scope就是会话级、模块级、类级、函数级。代表它的作用域,默认是function。什么是function?
函数是指单个的测试用例,也就是每一个测试用例。剩下的一些参数可以暂时不用管。
默认的是function,代表的是setUp和tearDown。测试用例是以函数的形式呈现的。既然是函数级别的,也就是一个测试用例一个测试用例的。类级别的参数,源码解析:
:arg scope: the scope for which this fixture is shared, one of
``"function"`` (default), ``"class"``, ``"module"``,
``"package"`` or ``"session"`` (``"package"`` is considered **experimental**
at this time).
参数有function,class。class就是setUpClass和tearDownClass。setUp和tearDown是作用在每个测试用例上,setUpClass和tearDownClass是作用在测试类当中,module就是整个Py文件。package是包,session是会话。这个会话是指测试用例会话。高级别的用法暂时用不上,就不用管它。session级别的,在接口自动化中可能用得上。每个测试用例可能都涉及数据库校验,它的前提就是数据库连接,得到一个数据库对象以及游标操作。那么就可以用session了。
在所有测试用例之前,先把这个东西运行一下,在后续所有操作中,直接用这个对象就行了。不需要在不同的测试用例中去连接。
实际上,接口自动化中用setUpClass就可以解决这个问题。
2.怎么知道在这个access_web函数中,哪些代码是前置,哪些代码是后置啊?
用关键字yield分隔前置操作和后置操作。如果没用后置,那么关键字yield都不用写。
代码如下:
import pytest
from selenium import webdriver
from PageObjects.login_page import LoginPage
from TestDatas import Comm_Datas as cd
driver=None
#声明它是一个fixture
@pytest.fixture(scope="class")
def access_web():#说明整个测试类只运行一次
global driver
#前置操作
print("=======所有测试用例执行之前的,setup====整个测试类只执行一次======")
driver=webdriver.Chrome()
driver.get(cd.web_login_url)
lg=LoginPage(driver)
yield(driver,lg) #分隔线;#后面接返回值
print("========所有测试用例之后的,teardown====整个测试用例只执行一次======")
driver.quit()
#后置操作
@pytest.fixture#默认是`setUp`和`tearDown`,所以这里不需要带括号。
def refresh_page():
global driver
#前置操作
yield
#后置操作
driver.refresh()
@pytest.fixture(scope="session")
def session_demo():
print("****我是整个测试会话期间的开始****")
yield
print("****我是整个测试会话期间的结束****")
@pytest.fixture(scope="class")
def class_demo():
print("****我是class的开始****")
yield
print("****我是class的结束****")
@pytest.fixture
def func_demo():
print("****我是function的开始****")
yield
print("****我是function的结束****")
fixture功能和ddt不能共用。现阶段不能适用ddt,它有它自己的方式来实现数据驱动。@pytest.mark.usefixtures("refresh_page") 可以写在测试用例前面,但是这个测试类下面每一个测试用例都用到了 fixture,大家的操作都是一样的,就没必要在每个函数前面都写上它。直接把它放在类前面就可以了。表示大家都用。
@pytest.mark.usefixtures("access_web")#在运行的时候,会去运行access_web函数
@pytest.mark.usefixtures("refresh_page")
class TestLogin:
# 正常用例 - 登陆成功 #fixture的函数名称,用来接收它的返回值
@pytest.mark.smoke
def test_login_2_success(self,access_web):#fixture的函数名称作为用例参数,用来接收fixture的返回值
logging.info("****登陆用例:正常场景:适用正确的用户名和密码登陆***")
#步骤 输入用户名和密码 点击登陆
access_web[1].login(ld.success_data["user"],ld.success_data["passwd"])
#断言 首页当中,如何找到退出这个元素
assert IndexPage(self.access_web[0]).isExist_logout_ele()
登陆的话,可以不需要它,用setUp和tearDown就可以解决这个问题。因为它的前置和后置只有它自己用,没用别人用。
第二种,私有化的方式:
假如TestLogin中9个前置后置都一样,只有1个前置后置不一样,该怎么做?
此代码运行可能会报错,用法需根据实际代码调试:
@pytest.mark.usefixtures("func_demo")#在运行的时候,会去运行access_web函数
@pytest.mark.usefixtures("class_demo")
@pytest.mark.demo
def test_demo():
print("ffffffffffffffff")
1.把单独的这一个拎取出来,定义成一个函数就好了,作为函数的形式放在外面。其它9个一样的都放在类当中。
2.假如10个测试用例中,5个是这样的,另外5个是另外一个样子的。就可以定义2个测试类。2个测试类用不一样的fixture。
以上私有化的方式的2种方法需要实操,根据实际情况判断2种方法的可用性以及调试。
