pytest + 登录禅道 :自动提交bug-编辑bug-确认bug-解决bug-关闭bug
一、Pycharm中创建项目结构
1.新建一个工程,工程名称自己定义,如:zentao
2.在工程的根目录下新建一个conftest.py(测试用例的一些fixture配置)和pytest.ini(改变pytest的运行方式)
3.在工程下创建以下package包:
--case:这个包放test开头的测试用例,也可以放一些非test开头的封装接口方法
--common:这个包放一些公共的方法,如:读取excel文件方法,读取mysql、oracle的脚本
--config:放一些配置文件,如邮箱的一些参数:收件人,发件人,密码等
4.在工程下创建以下文件夹:
--logs:这里存放日志信息
--report:这里存放测试报告
二、开始写脚本
思考:1.登录之后,需要提bug,然后操作bug,如何保持登录了?s=requests.session()可以实现保持会话;
2.假如登录,提bug,操作bug,都写在一个.py文件,可以使用s.get(...),s.post(...)操作所有请求,那若是这些操作在不同的.py文件呢?fixture自定义测试用例前置条件可以实现; 作用范围session(多个文件调用一次,可以跨.py文件调用),conftest.py文件在当前所在目录及以下目录生效;
3.若是请求地址写死,线下线上切换不方便,怎么办?当然fixture可以搞定了
2.1 由此,conftest.py脚本的内容确定了,如下:
#注意这里的ip改为自己服务器的ip哦
#conftest.py import requests import pytest @pytest.fixture(scope="session") def s(): ss=requests.session() return ss @pytest.fixture(scope="session") def host(): host="http://47.98.66.11:8899" return host
2.2 编写登录的脚本
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
|
# coding:utf-8
#test_login.py
import
re
import
pytest
import
hashlib
import
allure
@allure
.severity(
"blocker"
)
@allure
.epic(
"禅道登录,增删改查测试"
)
@allure
.feature(
"禅道登录"
)
@allure
.issue(
"http://47.98.66.11:8899/bug-browse-1-0-all.html"
)
class
Test_login:
@pytest
.fixture()
def
getrand(
self
,s,host):
while
True
:
r
=
s.get(host
+
"/user-login.html"
)
# print(r.text)
rand
=
re.findall(
"id='verifyRand' value='(.+?)'"
, r.text)
#print(rand)
if
len
(rand[
0
])
=
=
10
:
#break
print
(rand[
0
])
return
rand[
0
]
@pytest
.fixture()
def
md5(
self
,getrand):
first
=
hashlib.md5(
"P@ssw0rd"
.encode(
'utf-8'
)).hexdigest()
+
getrand
print
(first)
pwd
=
hashlib.md5(first.encode(
'utf-8'
)).hexdigest()
print
(pwd)
return
(getrand,pwd)
@allure
.title(
"登录用例"
)
def
test_login(
self
,md5,s,host):
data
=
{
"account"
:
"admin"
,
"password"
:md5[
1
],
"passwordStrength"
:
1
,
"referer"
:
"/"
,
"verifyRand"
:md5[
0
],
"keepLogin"
:
1
}
r
=
s.post(host
+
"/user-login.html"
,data
=
data)
#print(r.__dict__)
# print(dir(r))
# # print(r.text)
r1
=
s.get(host
+
"/my/"
)
#print(r1.text)
assert
'退出'
in
r1.text
|
2.3 提交bug
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
|
# coding:utf-8
#test_newbug.py
import
pytest
import
re
import
random
import
allure
@pytest
.fixture()
def
uppic_steps(s,host):
#上传图片
f
=
{
"localUrl"
:
"D:\\ch.jpg"
,
"imgFile"
:(
"ch.jpg"
,
open
(
"D:\\ch.jpg"
,
"rb"
),
"image/jpeg"
)}
r
=
s.post(host
+
"/file-ajaxUpload-5f37e08f8d109.html?dir=image"
,files
=
f)
#print(r.text)
print
(r.json())
#picurl=re.findall(',"url":"(.+?)"}',r.text)[0].replace("\\","")
picurl
=
r.json()[
"url"
]
print
(
"上传图片地址:{}"
.
format
(picurl))
return
picurl
@pytest
.fixture()
def
get_uid(s,host):
#获取uid
r
=
s.get(host
+
"/bug-create-1-0-moduleID=0.html"
)
uid
=
re.findall(
"kuid = '(.+?)'"
,r.text)
return
uid
@allure
.severity(
"critical"
)
@allure
.title(
"提bug"
)
def
test_newbug(s,uppic_steps,host,get_uid):
data
=
{
"product"
:
1
,
"module"
:
0
,
"project"
:
1
,
"openedBuild[]"
:
"trunk"
,
"assignedTo"
:
"admin"
,
"type"
:
"codeerror"
,
"title"
:
"接口自动化bug0815_15_附图片、附件:"
+
str
(random.randint(
0
,
1000
)),
"severity"
:
3
,
"pri"
:
3
,
"steps"
:
"<p>[步骤]<img src={} alt="
" /></p><br/><p>[结果]</p><br/><p>[期望]</p><br/>"
.
format
(uppic_steps),
"oldTaskID"
:
0
,
"status"
:
"active"
,
"uid"
:get_uid,
"caseVersion"
:
0
,
"case"
:
0
,
"result"
:
0
,
"testtask"
:
0
}
f
=
{
(
"files[]"
,(
"中国气候.jpg"
,
open
(
"D:\\中国气候.jpg"
,
"rb"
),
"image/jpeg"
)),
(
"labels[]"
,
"中国气候.jpg"
),
(
"files[]"
,(
"hl.jpeg"
,
open
(
"D:\\hl.jpeg"
,
"rb"
),
"image/jpeg"
)),
(
"labels[]"
,
"hl.jpeg"
)
}
r
=
s.post(host
+
"/bug-create-1-0-moduleID=0.html"
,data
=
data,files
=
f)
print
(
"提交bug,响应内容:{}"
.
format
(r.text))
|
2.4 编辑bug-确认bug-解决bug-关闭bug
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
# coding:utf-8
#test_operate.py
import
pytest
from
lxml
import
etree
import
re
import
time
import
allure
import
random
@pytest
.fixture()
def
get_id(s,host):
#查找未关闭状态的第一条bug的id
r
=
s.get(host
+
"/bug-browse-1-0-unclosed-0-id_desc.html"
)
er
=
etree.HTML(r.text)
id
=
er.xpath(
'//*[@id="bugList"]/tbody/tr[1]/td[1]/a'
)[
0
].text
#查找第一个的id
print
(
"提取第一个id为:{}"
.
format
(
id
))
return
id
def
get_idstatus(s,get_id,host):
#根据id,获取bug的状态
r
=
s.get(host
+
"/bug-browse-1-0-all.html"
)
er2
=
etree.HTML(r.text)
idtitle
=
er2.xpath(
'//*[@id="bugList"]/tbody/tr[@data-id={}]/td[6]'
.
format
(get_id))[
0
].get(
"title"
)
print
(get_id,idtitle)
return
idtitle
@allure
.title(
"修改bug"
)
def
test_edit(s,get_id,host):
r
=
s.get(host
+
"/bug-edit-{}.html"
.
format
(get_id))
kuid
=
re.findall(
"var kuid = '(.+?)'"
,r.text)
lasted
=
re.findall(
"id='lastEditedDate' value='(.+?)'"
,r.text)
data
=
{
"product"
:
1
,
"module"
:
0
,
"project"
:
1
,
"openedBuild[]"
:
"trunk"
,
"duplicateBug"
:
0
,
"assignedTo"
:
"admin"
,
"deadline"
:
"0000-00-00"
,
"type"
:
"codeerror"
,
"title"
:
"0818bug:"
+
str
(random.randint(
0
,
1000
)),
"severity"
:
3
,
"pri"
:
3
,
"steps"
:
"<p>[步骤]</p><br/><p>[结果]</p><br/><p>[期望]</p><br/>"
,
"status"
:
"active"
,
"lastEditedDate"
:lasted,
"uid"
: kuid,
"caseVersion"
:
0
,
"comment"
:
"修改bug"
}
s.post(r.url,data
=
data)
assert
get_idstatus(s, get_id, host)
=
=
"激活"
@allure
.title(
"确认bug"
)
def
test_confirm(s,get_id,host):
r
=
s.get(host
+
"/bug-confirmBug-{}.html?onlybody=yes"
.
format
(get_id))
kuid
=
re.findall(
"var kuid = '(.+?)'"
, r.text)[
0
]
data
=
{
"assignedTo"
:
"admin"
,
"type"
:
"codeerror"
,
"pri"
:
3
,
"status"
:
"active"
,
"comment"
:
"ok,稍后修复"
,
"uid"
:kuid
}
r1
=
s.post(r.url, data
=
data)
print
(
"确认后,响应内容:{}"
.
format
(r1.text))
print
(get_id)
assert
get_idstatus(s, get_id, host)
=
=
"激活"
@allure
.title(
"解决bug"
)
def
test_resolve(s,get_id,host):
#解决bug
r
=
s.get(host
+
"/bug-resolve-{}.html?onlybody=yes"
.
format
(get_id))
kuid
=
re.findall(
"var kuid = '(.+?)'"
,r.text)[
0
]
print
(
type
(kuid),kuid,r.url)
datas
=
{
"resolution"
:
"bydesign"
,
"resolvedBuild"
:
"trunk"
,
"resolvedDate"
:time.strftime(
"%Y-%m-%d %H:%M:%S"
,time.localtime()),
"assignedTo"
:
"admin"
,
"status"
:
"resolved"
,
"comment"
:
"不予修复"
,
"uid"
:kuid
}
r1
=
s.post(r.url, data
=
datas)
print
(
"修改为已解决,响应内容:{}"
.
format
(r1.text))
print
(get_id)
assert
get_idstatus(s,get_id,host)
=
=
"已解决"
@allure
.title(
"关闭bug"
)
def
test_close(s,host,get_id):
#关闭bug
url
=
host
+
"/bug-close-{}.html?onlybody=yes"
.
format
(get_id)
r
=
s.get(url)
kuid
=
re.findall(
"kuid = '(.+?)'"
,r.text)
data
=
{
"status"
:
"closed"
,
"comment"
:
"ok"
,
"uid"
:
"kuid"
}
r1
=
s.post(url,data
=
data)
print
(r1.text)
assert
get_idstatus(s,get_id,host)
=
=
'已关闭'
|
2.5 为了展示自己的劳动成果,报告是不可少的
1
2
3
4
5
6
7
8
|
#pytest.ini
[pytest]
#pytest-html生成报告
#addopts=-s --html=report/a.html --self-contained-html
#allure-pytest 生成报告
addopts
=
-
s
-
-
alluredir report
/
b
|
2.6 zentao文件下,打开cmd,执行pytest
pytest执行完毕,继续输入allure serve report/b 自动展示html格式报告(注意:report/b可以随意命名,但必须与pytest.ini中的内容一致)
注意:pytest可以在zentao目录下执行,也可以在case目录下执行,但这样report/b所在的目录就不同了;根据pytest.ini,执行pytest会在pytest当前所在目录生成report/b目录,若是report/b不存在则直接创建,若是存在则使用已有的;
执行pytest时,一定要删除b目录,不然可能会产生冗余数据;
三、写代码过程中,想要调试某个脚本;如,提交bug;
那么需要执行登录脚本和提交bug脚本;
在case目录下,打开cmd,执行pytest -s test_login.py test_newbug.py
若是想要调试登录,那直接执行pytest -s test_login.py
原文地址https://www.cnblogs.com/canglongdao/p/13526810.html