300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > allure 测试报告本地打开_Pytest和Allure测试框架(二)

allure 测试报告本地打开_Pytest和Allure测试框架(二)

时间:2021-05-13 08:35:12

相关推荐

allure 测试报告本地打开_Pytest和Allure测试框架(二)

七, 单元自动化测试pytest和allure在测试中应用 自动执行

1, 单元测试测试报告展示

2, conftest中编写driver,范围session,使用 addfinalizer在测试结束后关闭浏览器

3, 前端自动化测试-百度搜索功能实战演示

报告可以展示许多不同类型的附件,用来补充测试,步骤等信息

allure.attach(body, name, attachment_type, extension)

body - 要写入文件的原始内容。

name - 包含文件名的字符串

attachment_type- 其中一个allure.attachment_type值

extension - 提供的将用作创建文件的扩展名

或者 allure.attach.file(source, name, attachment_type, extension)

source - 包含文件路径的字符串。

# -*- coding: utf-8 -*-

# @Time : /3/12 11:46

# @Author : zzt

import allure

import pytest

@allure.feature('这里是一级标签')

class TestAllure():

@allure.title("用例标题0")

@allure.story("这里是第一个二级标签")

@pytest.mark.parametrize('param', ['青铜', '白银', '黄金'])

def test_0(self, param):

allure.attach('附件内容是:'+param, '我是附件名', allure.attachment_type.TEXT)

@allure.title("用例标题1")

@allure.story("这里是第二个二级标签")

def test_1(self):

allure.attach.file(r'E:\Myproject\pytest-allure\test\test_1.jpg', '我是附件截图的名字', attachment_type=allure.attachment_type.JPG)

@allure.title("用例标题2")

@allure.story("这里是第三个二级标签")

@allure.severity(allure.severity_level.NORMAL)

def test_2(self):

pass

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

执行结果如下:

4,源码:Github:/linda883/py_techDemo

5, CI/CD使用jenkins进行持续集成

在Jenkins集成相信大家都会就不讲了,或者看我的持续集成博客

三, Pytest -fixture

下面都有实战很详细-fixture确实牛逼

pytest 相较于 unittest 最为跳跃的一点应该就是 fixture 机制

对于unittest来说,每个用例的类中都需要去写入setUp和tearDown。也就是我们所说的前置和后置,

而不可避免的,很多用例的前置和后置都是一样(例如很多用例都需要前置登录,后置退出),于是我们需要重复的复制粘贴,这样导致工作量增加,代码量也增加,界面也显得冗杂。

所以此时pytest中fixture机制便要闪亮登场了。

通俗的讲:fixture = 前置+后置

而方便的是:如果很多用例都有同样的前置和后置,那么我就只实现一个,然后需要的用例就去调用就好了。

1.机制:与测试用例同级,或者是测试用例的父级,创建一个conftest.py文件。

2.conftest.py文件里:放所有的前置和后置。不需要用例.py文件主动引入conftest文件。

3.定义一个函数:包含前置操作+后置操作。

4.把函数声明为fixture :在函数前面加上 @pytest.fixture(作用级别=默认为function)

5.fixture的定义。

如果有返回值,那么写在yield后面。(yield的作用就相当于return)

在测试用例当中,调用有返回值的fixture函数时,函数名称就是代表返回值。

在测试用例当中,函数名称作为用例的参数即可。

1.如下:定义一个函数名叫open_url的fixture前后置,前置为打开链接,后置为退出浏览器

@pytest.fixture(scope=“class”) #定义scope的范围

def open_url():

# 前置

driver = webdriver.Chrome()

driver.get(url) #url为链接地址

yield driver #yield之前代码是前置,之后的代码就是后置。

# 后置

driver.quit()

1

2

3

4

5

6

7

这样我们就定义了一个叫做 open_url 的 fixture

2.在我们要用这个前后置的类前面 我们用@pytest.mark.usefixtures(fixture函数名)

就可以直接调用上面定义好的这个前后置

可以看到 在TestLogin 这个类中 我们不再去编写setup 和 teardown. 直接写我们的中间过程就可以了。是不是很方便了?

3.进阶方法:conftest中定义多个fixture,一个fixture可以是另一个fixture的前后置,期间还是用field隔开前后置

如上图中可以看到我class中另外还引用了一个名为refresh_page的fixture,直接上代码:

# 刷新页面 - 定义的第二个fixture

@pytest.fixture

def refresh_page(open_url):

yield

open_url.refresh()

1

2

3

4

5

直接将open_url作为了另一个fixture的前置引用进来,用yield隔开,当用例中执行完open_url前后置后,再执行了一次refresh的后置。

执行顺序:open_url yield 之前代码 – 用例代码 – open_url yield 之后代码 --》 refresh_page yield 之后代码

是不是很妙,可以解决许多用例流程环环相扣时的麻烦。

4.说到上面的多个fixture调用,很多人就会疑惑,会不会fixture之间相互冲突。

当然是不会了,fixture在conftest.py当中就已经决定了他的用例域,他会主动去区分你这个fixture是作用在哪个用例域。

首先我们看一下框架中对于fixture函数的定义:

scope便是定义用例域的范围:

function:默认范围,每一个函数或方法都会调用,不填写时便是它

class:每一个类调用一次

module: 每一个.py文件调用一次,文件中可以有多个function和class

session:多个文件调用一次,可以跨文件,如在.py文件中,每一个.py文件就是module

范围:

session > module > class > function

所以在调用时各个fixture之间并不会相互冲突。

5,fixture的自动应用autouse

autouse调用例子:**

当管理用例比较多的时候,这种方法比较方便高效,但是用该功能时也要小心,一定要注意fixture的作用范围。需要注意的是,当使用这种方式时,就不能使用返回值的功了。autouse默认设置为False。当默认为False,就可以选择用上面两种方式来试用fixture。当设置为True时,所有的test都会自动调用这个fixture。autouse遵循scope="关键字参数"规则:当scope="session"时,无论怎样定义只运行一次;当scope="module"时,每个py文件只运行一次;当scope="class"时,每个class只运行一次(但是一个文件中包括function和class时,会在每个function(不在class中)运行一次);当scope="function"时,每个function运行一次;

‘’’平常写自动化用例会写一些前置的fixture操作,用例需要用到就直接传该函数的参数名称就行了。当用例很多的时候,每次都传这个参数,会比较麻烦。

fixture里面有个参数autouse,默认是Fasle没开启的,可以设置为True开启自动使用fixture功能,这样用例就不用每次都去传参了

设置autouse=True

autouse设置为True,自动调用fixture功能

start设置scope为module级别,在当前.py用例模块只执行一次,autouse=True自动使用[图片]open_home设置scope为function级别,

每个用例前都调用一次,自动使用

import pytest

@pytest.fixture(scope="module",autouse=True)

def start(request):

print("\n----开始执行module------")

print('module : %s'% request.module.__name__)

print('------启动浏览器-------')

yield

print("------结束测试 end!----------")

@pytest.fixture(scope="function",autouse=True)

def open_home(request):

print("function:%s \n--回到首页--"% request.function.__name__)

def test_01():

print('----用例01-----')

def test_02():

print('----用例02-----')

if __name__ == '__main__':

pytest.main(["-s","autouse.py"])

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

执行结果

----开始执行module------

module : autouse

------启动浏览器-------

function:test_01

--回到首页--

.----用例01-----

function:test_02

--回到首页--

.----用例02-----

------结束测试 end!----------

1

2

3

4

5

6

7

8

9

10

四,参数化与数据驱动框架实现

参数化1

import pytest

@pytest.mark.parametrize('test_input,expected',[('3+5',8),

('2-1',1),('7*5',30)])

def test_eval(test_input,expected):

assert eval(test_input)==expected----eval把字符串转换成表达式

est_param.py::test_eval[2-1-1]

test_param.py::test_eval[7*5-30] PASSED [ 33%]PASSED [ 66%]FAILED [100%]

test_param.py:3 (test_eval[7*5-30])

35 != 30

Expected :30

Actual :35

<Click to see difference>

test_input = '7*5', expected = 30

@pytest.mark.parametrize('test_input,expected',[('3+5',8),

('2-1',1),('7*5',30)])

def test_eval(test_input,expected):

> assert eval(test_input)==expected

E assert 35 == 30----提示把30改成35

test_param.py:7: AssertionError

Assertion failed

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

参数化2

import pytest

test_user_data=['linda','sai','tom']

@pytest.fixture(scope='module')

def login(request):

user=request.param

print('打开首页登陆%s'%user)

return user

#indirect=True是把login当作函数去执行

@pytest.mark.parametrize('login',test_user_data,indirect=True)

def test_cart(login):

usera=login

print('不同用户添加购物车%s'%usera)

assert usera!=''

Process finished with exit code 0

打开首页登陆linda

PASSED [ 33%]不同用户添加购物车linda

打开首页登陆sai

PASSED [ 66%]不同用户添加购物车sai

打开首页登陆tom

PASSED [100%]不同用户添加购物车tom

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

参数化3

import pytest

test_user_data=[

{'user':'linda','password':'8888'},

{'user':'servenruby','password':'123456'},

{'user':'test01','password':''}

]

@pytest.fixture(scope='module')

def login_r(request):

#可以通过dict形式,虽然传递一个参数,但通过key的方式可以达到累死传入多个参数的效果

user=request.param['user']

pwd=request.param['password']

print('\n打开首页准备登陆,登陆用户%s,密码%s'%(user,pwd))

if pwd:

return True

else:

return False

#这是pytest参数化驱动,indeirect=True是把login_r当作函数去执行

@pytest.mark.parametrize('login_r',test_user_data,indirect=True)

def test_cart(login_r):

#登陆用例

a=login_r

print('测试用例中login_r的返回值%s'%a)

assert a,'失败原因,密码为空'

开首页准备登陆,登陆用户linda,密码8888

PASSED [ 33%]测试用例中login_r的返回值True

打开首页准备登陆,登陆用户servenruby,密码123456

PASSED [ 66%]测试用例中login_r的返回值True

打开首页准备登陆,登陆用户test01,密码

FAILED [100%]测试用例中login_r的返回值False

打开首页准备登陆,登陆用户linda,密码8888

PASSED [ 33%]测试用例中login_r的返回值True

打开首页准备登陆,登陆用户servenruby,密码123456

PASSED [ 66%]测试用例中login_r的返回值True

打开首页准备登陆,登陆用户test01,密码

FAILED [100%]测试用例中login_r的返回值False

test_mark_param_request2.py:19 (test_cart[login_r2])

login_r = False

@pytest.mark.parametrize('login_r',test_user_data,indirect=True)

def test_cart(login_r):

#登陆用例

a=login_r

print('测试用例中login_r的返回值%s'%a)

> assert a,'失败原因,密码为空'

E AssertionError: 失败原因,密码为空

E assert False

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

参数化3*3

import pytest

test_user_data1=[{'user':'linda','password':'888888'},

{'user':'servenruby','password':'123456'},

{'user':'test01','password':''}]

test_user_data2=[{'q':'中国平安','count':3,'page':1},

{'q':'阿里巴巴','count':2,'page':2},

{'q':'pdd','count':3,'page':1}]

@pytest.fixture(scope='module')

def login_r(request):

#这是接受不了输入的参数,接收一个参数

user=request.param['user']

pwd=request.param['password']

print('\n用户名:%s,密码:%s'%(user,pwd))

@pytest.fixture(scope='module')

def query_param(request):

q=request.param['q']

count=request.param['count']

page=request.param['page']

print('查询的搜索词%s'%q)

return request.param

#这是pytest的数据驱动,indeirect=True是把login_r当作函数去执行

#从下往上执行

#两个数据进行组合测试,有3*3个测试用例执行(test_user_data1的个数*test_user_data2的个数

@pytest.mark.parametrize('query_param',test_user_data2,indirect=True)

@pytest.mark.parametrize('login_r',test_user_data1,indirect=True)

def test_login(login_r,query_param):

#登陆用例

print(login_r)

print(query_param)

pytest_mark_request3.py::test_login[login_r1-query_param0] ✓ 44% ████▌ 查询的搜索词pdd

None

{'q': 'pdd', 'count': 3, 'page': 1}

pytest_mark_request3.py::test_login[login_r1-query_param2] ✓ 56% █████▋

用户名:linda,密码:888888

None

{'q': 'pdd', 'count': 3, 'page': 1}

pytest_mark_request3.py::test_login[login_r0-query_param2] ✓ 67% ██████▋

用户名:test01,密码:

None

{'q': 'pdd', 'count': 3, 'page': 1}

pytest_mark_request3.py::test_login[login_r2-query_param2] ✓ 78% ███████▊ 查询的搜索词阿里巴巴

None

{'q': '阿里巴巴', 'count': 2, 'page': 2}

pytest_mark_request3.py::test_login[login_r2-query_param1] ✓ 89% ████████▉ 查询的搜索词中国平安

None

{'q': '中国平安', 'count': 3, 'page': 1}

pytest_mark_request3.py::test_login[login_r2-query_param0] ✓ 100% ██████████

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。