文章总览图
1.后面的用例需要用到第一条用例的返回结果里的某些值,怎么去处理这种依赖关系?
方法一: 第1条用例写在setUp里面,每次请求的时候,在setUp里面重新请求第一条用例。 缺点就是关联性比较强,一步错,步步错。
方法二: 全局变量 缺点就是关联性比较强,一步错,步步错。
外面的是全局变量,函数里面的是局部变量。 如果要修改全局变量的值,怎么去改? 先global
声明全局变量,才能去修改局部变量的值。
方法三: 反射---不强调 这种方法更简单。
setattr(GetData,"Cookie","小白")
# 类名 属性名 新值
可以直接把类里面的属性值做修改,进行更新。缺点就是关联性比较强,一步错,步步错。
数据参数化: 可以解决用例的关联性强,一步错,步步错的问题。
Http请求:创建实例.方法(参数)
下面操作需要先在Python里面安装requests库,pip install requests
2.代码如下
单元测试思路:第1个地址是登录的接口地址,第2个地址是登录进去后进行充值的接口地址。两个接口地址是同一个网站的。
由于清菡没有找到这样的接口,所以用的别的接口地址,学的是思路。
先创建一个http_request.py文件,调用requests库,对get和post请求成功封装。
代码语言:javascript复制#来自文件http_request.py
import requests
class HttpRequest:
'''利用request封装get请求和post请求'''
def http_request(self,url,data,method,cookie=None):
'''url:请求的地址 http://xxx:port
param:传递的参数 非必填参数 字典的格式传递参数
method:请求方式支持get以及post 字符串形式的参数
cookie:请求的时候传递的cookie值'''
if method.lower()=='get':
res = requests.get(url, data, cookies=cookie)
else:
res=requests.post(url,data,cookies=cookie)#响应结果的消息实体 http response包含响应头,响应状态码,响应正文,Cookie
return res#返回一个消息实体
if __name__ =='__main__':
url = 'http://v.juhe.cn/xhzd/query'
data = {"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
res=HttpRequest().http_request(url,data,'post')
print("登录结果是:", res.json())
#充值
recharge_url='http://v.juhe.cn/xhzd/query'
recharge_data={"key":"e0dd844ff0669814b529da934a094a83","word":'聚'}
recharges_res=HttpRequest().http_request(recharge_url,recharge_data,'get',res.cookies)
print("充值结果是:",recharges_res.json())
方法一:setUp
写在setUp
里面,每次请求的时候在setUp
里面重新请求第一条用例。
#来自文件test_http.py
#输入错误的密码和充值为负数没有加断言,所以结果全部通过。
import unittest
from test_demo.http_request import HttpRequest
class TestHttp(unittest.TestCase):
def setUp(self):
#登录
self.login_url='http://v.juhe.cn/xhzd/query'
self.login_data={"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
#充值的URL
self.recharge_url= 'http://v.juhe.cn/xhzd/query'
#获取登录后的cookies
self.cookies=HttpRequest().http_request(self.login_url,self.login_data,'get').cookies
print("setUp函数里面登录后产生的cookies是:{}".format(self.cookies))
def test_login_normal(self):#正常登录
data={"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
res=HttpRequest().http_request(self.login_url,data,'get')
try:
self.assertEqual('返回成功',res.json()['reason'])
except AssertionError as e:
print("test_login_normal's error is{}".format(e))
raise e
print(res.json())
def test_login_wrong_pwd(self):#输入错误的密码
data={"key": "e0dd844ff0669814b529da934a094a83", "word": ''}
res=HttpRequest().http_request(self.login_url,data,'get')
print(res.json())
def test_recharge_normal(self):#正常充值
recharge_data = {"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',self.cookies)#加了一个cookies
try:
self.assertEqual('返回成功', res.json()['reason'])
except AssertionError as e:
print("test_recharge_normal's error is{}".format(e))
raise e
print(res.json())
def test_recharge_negative(self):#充值为负数
recharge_data = {"key": "e0dd844ff0669814b529da934a094a83", "word": ''}
res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',self.cookies)#加了一个cookies
print(res.json())
def tearDown(self):
pass
写断言的时候,需要把响应结果里面的值填写进去。
代码语言:javascript复制#来自文件test_suite.py
#用的不是登录-充值的接口,测试的时候最好找到能登录进去并进行充值的接口。
import unittest
import HTMLTestRunner
from test_demo import test_http#模块名
suite=unittest.TestSuite()
#通过loader方式来加载用例,其它的方式也可以尝试。
loader=unittest.TestLoader()
suite.addTest(loader.loadTestsFromModule(test_http))
#执行
with open("test_summer.html",'wb')as file:
runner=HTMLTestRunner.HTMLTestRunner(stream=file, verbosity=2,title="单元测试",description=None,tester="清菡")
runner.run(suite)
文件夹下已创建文件http_request.py,文件test_http.py和文件test_suite.py,运行文件test_suite.py。
输出结果如下:
输入错误的密码和充值为负数没有加断言,所以结果全部通过。
输入错误的密码和充值为负数的用例中增加了断言
代码语言:javascript复制#来自文件test_http_Assert.py
import unittest
from test_demo.http_request import HttpRequest
class TestHttp(unittest.TestCase):
def setUp(self):
#登录
self.login_url='http://v.juhe.cn/laohuangli/d'
self.login_data={"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-09'}
#充值的URL
self.recharge_url= 'http://v.juhe.cn/laohuangli/d'
#获取登录后的cookies
self.cookies=HttpRequest().http_request(self.login_url,self.login_data,'get').cookies
print("setUp函数里面登录后产生的cookies是:{}".format(self.cookies))
def test_login_normal(self):#正常登录
data={"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-09'}
res=HttpRequest().http_request(self.login_url,data,'get')
try:
self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
except AssertionError as e:
print("test_login_normal's error is{}".format(e))
raise e
print(res.json())
def test_login_wrong_pwd(self):#输入错误的密码
data={"key": "abf91475fc19f66c2f1fe567edd75257", "date": ''}
res=HttpRequest().http_request(self.login_url,data,'get')
try:
self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
except AssertionError as e:
print("test_login_wrong_pwd's error is{}".format(e))
raise e
print(res.json())
def test_recharge_normal(self):#正常充值
recharge_data = {"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-09'}
res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',self.cookies)#加了一个cookies
try:
self.assertEqual('超过每日可允许请求次数!', res.json()['reason'])
except AssertionError as e:
print("test_recharge_normal's error is{}".format(e))
raise e
print(res.json())
def test_recharge_negative(self):#充值为负数
recharge_data ={"key": "abf91475fc19f66c2f1fe567edd75257", "date": ''}
res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',self.cookies)#加了一个cookies
try:
self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
#预期结果
except AssertionError as e:
print("test_recharge_negative's error is{}".format(e))
raise e#注意:实际结果与预期结果不符合的情况下没加raise e 通过,加了raise e 用例才抛出错误。
#如果实际结果和预期结果是一致的,加raise e 和不加raise e,用例都是通过的。
print(res.json())
def tearDown(self):
pass
前1次代码,因为输入错误的密码和充值为负数没有加断言,所以结果全部通过。可以在上次的结果中取这块的值放进断言中,为错误的密码和充值为负数的用例中增加断言。
图片中仅供参考,根据实际的接口情况,取值。
代码语言:javascript复制#来自文件test_suite.py
#此接口不是登录-充值的接口
import unittest
import HTMLTestRunner
from test_demo import test_http_Assert#模块名
suite=unittest.TestSuite()
#通过loader方式来加载用例,其它的方式也可以尝试。
loader=unittest.TestLoader()
suite.addTest(loader.loadTestsFromModule(test_http_Assert))
#执行
with open("test_summer.html",'wb')as file:
runner=HTMLTestRunner.HTMLTestRunner(stream=file, verbosity=2,title="单元测试",description=None,tester="清菡")
runner.run(suite)
文件夹下已创建文件http_request.py,文件test_http_Assert.py和文件test_suite.py,运行文件test_suite.py。
输出结果如下:
注意:实际结果与预期结果不符合的情况下,没加raise e 通过,加了raise e 用例才抛出错误。如果实际结果和预期结果是一致的,加raise e和不加raise e,用例都是通过的。
实际结果与预期结果不符合的情况下,加了raise e 用例抛出错误。
方法二:全局变量
代码语言:javascript复制#文件来自quanjubianliang.py
import unittest
from test_demo.http_request import HttpRequest
COOKIE=None#全局变量
class TestHttp(unittest.TestCase):
def setUp(self):
#登录
self.login_url='http://v.juhe.cn/xhzd/query'
#充值的URL
self.recharge_url= 'http://v.juhe.cn/xhzd/query'
#获取登录后的cookies
# self.cookies=Httprequest().http_request(self.login_url,self.login_data,'get').cookies
# print("setUp函数里面登录后产生的cookies是:{}".format(self.cookies))
def test_login_normal(self):#正常登录
global COOKIE#声明全局变量
data={"key":"e0dd844ff0669814b529da934a094a83","word":'聚'}
res=HttpRequest().http_request(self.login_url,data,'get')
#if条件语句,后面为空就是False,不为空就是True。res.cookies不为空就是有cookie,有cookie的时候再去做替换。
if res.cookies:#如果cookie有的话,就更新COOKIE
COOKIE=res.cookies
try:
self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
except AssertionError as e:
print("test_login_normal's error is{}".format(e))
raise e
print(res.json())
def test_login_wrong_pwd(self):#输入错误的密码登录
data={"key":"e0dd844ff0669814b529da934a094a83","word":''}
res=HttpRequest().http_request(self.login_url,data,'get')
try:
self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
except AssertionError as e:
print("test_login_normal's error is{}".format(e))
raise e
print(res.json())
def test_recharge_normal(self):#登录后正常充值
global COOKIE#加了global才能修改它的值,局部变量要修改全局变量的值,就要声明它是个全局变量。
recharge_data = data={"key":"e0dd844ff0669814b529da934a094a83","word":'聚'}
res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',COOKIE)#加了一个全局变量cookie
try:
self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
except AssertionError as e:
print("test_recharge_normal's error is{}".format(e))
raise e
print(res.json())
def test_recharge_negative(self):#登录后充值为负数
global COOKIE
recharge_data =data={"key":"e0dd844ff0669814b529da934a094a83","word":''}
res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',COOKIE)#加了一个全局变量cookie
try:
self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
except AssertionError as e:
print("test_recharge_negative's error is{}".format(e))
raise e#注意:实际结果与预期结果不符合的情况下没加raise e 通过,加了raise e 用例才抛出错误。
#如果实际结果和预期结果是一致的,加raise e 和不加raise e,用例都是通过的。
print(res.json())
def tearDown(self):
pass
代码语言:javascript复制#来自文件test_suite.py
#不是登录-充值的接口
import unittest
import HTMLTestRunner
from test_demo import quanjubianliang#模块名
suite=unittest.TestSuite()
#通过loader方式来加载用例,其它的方式也可以尝试。
loader=unittest.TestLoader()
suite.addTest(loader.loadTestsFromModule(quanjubianliang))
#执行
with open("test_summer.html",'wb')as file:
runner=HTMLTestRunner.HTMLTestRunner(stream=file, verbosity=2,title="单元测试",description=None,tester="清菡")
runner.run(suite)
文件夹下已创建文件http_request.py,文件quanjubianliang.py和文件test_suite.py,运行文件test_suite.py。
输出结果如下:
方法三:反射
代码语言:javascript复制#来自文件get_data.py
class GetData:
Cookie=None#存储cookie,初始值为None
代码语言:javascript复制#文件来自fanshe.py
import unittest
from test_demo.http_request import HttpRequest
from test_demo.get_data import GetData
class TestHttp(unittest.TestCase):
def setUp(self):
#登录
self.login_url='http://v.juhe.cn/laohuangli/d'
#充值的URL
self.recharge_url= 'http://v.juhe.cn/laohuangli/d'
def test_login_normal(self):#正常登录
data={"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-09'}
res=HttpRequest().http_request(self.login_url,data,'get')
#if条件语句,后面为空就是False,不为空就是True。res.cookies不为空就是有cookie,有cookie的时候再去做替换。
if res.cookies:#如果cookie有的话,就更新COOKIE
setattr(GetData,'Cookie',res.cookies)
try:
self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
except AssertionError as e:
print("test_login_normal's error is{}".format(e))
raise e
print(res.json())
def test_login_wrong_pwd(self):#输入错误的密码登录
data={"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-11'}
res=HttpRequest().http_request(self.login_url,data,'get')
try:
self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
except AssertionError as e:
print("test_login_normal's error is{}".format(e))
raise e
print(res.json())
def test_recharge_normal(self):#登录后正常充值
recharge_data = {"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-09'}
res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',getattr(GetData,"Cookie"))
try:
self.assertEqual('超过每日可允许请求次数!', res.json()['reason'])
except AssertionError as e:
print("test_recharge_normal's error is{}".format(e))
raise e
print(res.json())
def test_recharge_negative(self):#登录后充值为负数
recharge_data = {"key": "abf91475fc19f66c2f1fe567edd75257", "date": '-2014-09-09'}
res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',getattr(GetData,"Cookie"))
try:
self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
except AssertionError as e:
print("test_recharge_negative's error is{}".format(e))
raise e
print(res.json())
def tearDown(self):
pass
代码语言:javascript复制#文件来自test_suite.py
#不是登录-充值的接口
import unittest
import HTMLTestRunner
from test_demo import fanshe#模块名
suite=unittest.TestSuite()
#通过loader方式来加载用例,其它的方式也可以尝试。
loader=unittest.TestLoader()
suite.addTest(loader.loadTestsFromModule(fanshe))
#执行
with open("test_summer.html",'wb')as file:
runner=HTMLTestRunner.HTMLTestRunner(stream=file, verbosity=2,title="单元测试",description=None,tester="清菡")
runner.run(suite)
文件夹下已创建文件http_request.py,get_data.py文件,fanshe.py和文件test_suite.py,运行文件test_suite.py。
输出结果如下:
介绍反射的原理
代码语言:javascript复制#介绍反射的原理
class GetData:
Cookie=None
# Cookie='小郭'
if __name__ == '__main__':
print(GetData.Cookie)
setattr(GetData,"Cookie","小白")#1 可以直接把类里面的属性值做修改
# 类名 属性名 新值
print(hasattr(GetData,"Cookie"))#2 判断是否有这个属性值
print(getattr(GetData,"Cookie"))#3 attribute 属性 获取这个属性值
delattr(GetData,"Cookie")#4 把这个属性删掉
# print(GetData.Cookie)
print(hasattr(GetData,"Cookie"))#判断是否有这个属性值
直接运行代码就可以。
参数化
地址不一样,测试数据不同,断言的期望结果不同,除了这几个不同,其它的都是高度相似的,80%相似,可以用参数化。
参数化 url
data
expected
#来自文件get_data.py
class GetData:
Cookie=None#存储cookie,初始值为None
代码语言:javascript复制#来自文件http_request.py
import requests
class HttpRequest:
'''利用request封装get请求和post请求'''
def http_request(self,url,data,method,cookie=None):
'''url:请求的地址 http://xxx:port
param:传递的参数 非必填参数 字典的格式传递参数
method:请求方式支持get以及post 字符串形式的参数
cookie:请求的时候传递的cookie值'''
if method.lower()=='get':
res = requests.get(url, data, cookies=cookie)
else:
res=requests.post(url,data,cookies=cookie)#响应结果的消息实体 http response包含响应头,响应状态码,响应正文,Cookie
return res#返回一个消息实体
if __name__ =='__main__':
url = 'http://v.juhe.cn/xhzd/query'
data = {"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
res=HttpRequest().http_request(url,data,'post')
print("登录结果是:", res.json())
#充值
recharge_url='http://v.juhe.cn/xhzd/query'
recharge_data={"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
recharges_res=HttpRequest().http_request(recharge_url,recharge_data,'get',res.cookies)
print("充值结果是:",recharges_res.json())
代码语言:javascript复制#来自文件test_http.py
#开拓思维必学
import unittest
from class_1101.http_request import HttpRequest
from class_1101.get_data import GetData
class TestHttp(unittest.TestCase):
def setUp(self):
pass
# 数据给它参数化,通过初始化传参,实现参数化
def __init__(self,methodName,url,data,method,expected):#通过初始化函数来传参数
super(TestHttp,self).__init__(methodName)#父类的方法要保留,用的超继承。
self.url=url
self.data=data
self.method=method
self.expected=expected
def test_api(self):#接口用例
res=HttpRequest().http_request(self.url,self.data,self.method,getattr(GetData,'Cookie'))
if res.cookies:#如果cookie有的话,就更新COOKIE
setattr(GetData,'Cookie',res.cookies)#反射
try:
self.assertEqual(self.expected,res.json()['reason'])
except AssertionError as e:
print("test_api's error is{}".format(e))
raise e
print(res.json())
def tearDown(self):
pass
代码语言:javascript复制#来自文件test_suite.py
#不是登录-充值的接口
import unittest
import HTMLTestRunner
from class_1101.test_http import TestHttp#类名
#列表里面嵌套了字典
test_data=[{"url":'http://v.juhe.cn/xhzd/query', #期望值
"data":{"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'},"expected":'超过每日可允许请求次数!','method':'get'},
{"url":'http://v.juhe.cn/xhzd/query',
"data":{"key": "e0dd844ff0669814b529da934a094a83", "word": ''},"expected":'超过每日可允许请求次数!','method':'post'},
{"url":'http://v.juhe.cn/xhzd/query',
"data": {"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'},"expected":'超过每日可允许请求次数!','method':'get'},
{"url":'http://v.juhe.cn/xhzd/query',
"data" :{"key": "e0dd844ff0669814b529da934a094a83", "word": ''},"expected":'超过每日可允许请求次数!','method':'post'}]
suite=unittest.TestSuite()
#遍历数据
for item in test_data:#创建实例
suite.addTest(TestHttp("test_api",item['url'],item['data'],item['method'],item['expected']))
#实例的方式去加载用例url,data,method,expected
#执行
with open("test_summer.html",'wb')as file:
runner=HTMLTestRunner.HTMLTestRunner(stream=file, verbosity=2,title="单元测试",description=None,tester="清菡")
runner.run(suite)
文件夹下已创建文件http_request.py,get_data.py文件,test_http.py和文件test_suite.py,运行文件test_suite.py。
输出结果如下: