本文共 9487 字,大约阅读时间需要 31 分钟。
setUp和tearDown是每一次test_xx都会执行的,即使加上@classmethod也做不到每个类只执行一次
import unittestclass TestDemo001(unittest.TestCase): @classmethod def setUp(cls): print("====setup========") @classmethod def tearDown(cls): print("=====tearDown======") def test_001(self): print("======test001====") def test_002(self): print("======test002======")if __name__ == "__main__": unittest.main()
setUpClass和tearDownClass是每个类只执行一次,而且必须配合@classmethod才会生效
import unittestclass TestDemo001(unittest.TestCase): @classmethod def setUpClass(cls): print("====setup========") @classmethod def tearDownClass(cls): print("=====tearDown======") def test_001(self): print("======test001====") def test_002(self): print("======test002======")if __name__ == "__main__": unittest.main()
import requestsimport jsondata = { "username":"aaa", "password":"123123"}url = "http://c.m.163.com/nc/article/headline/T1348647853363/0-40.html"class RunMain: def __init__(self,url,method,data=None): self.res = self.run_main(url,method,data) def send_get(self,url,data=None): result = requests.get(url).json() return json.dumps(result,indent=2,sort_keys="true") def send_post(self,url,data): result = requests.post(url,data).json() return json.dumps(result,indent=2,sort_keys="true") def run_main(self,url,method,data=None): res = None if method == "GET": res = self.send_get(url,data) else: res = self.send_post(url,data) return resif __name__ == "__main__": run = RunMain(url,"GET",data) print(run.res)
基本的断言方法提供了测试结果是True还是False。所有的断言方法都有一个msg参数,如果指定msg参数的值,则将该信息作为失败的错误信息返回。
序号 | 断言方法 | 断言描述 |
---|---|---|
1 | assertEqual(arg1, arg2, msg=None) | 验证arg1=arg2,不等则fail |
2 | assertNotEqual(arg1, arg2, msg=None) | 验证arg1 != arg2, 相等则fail |
3 | assertTrue(expr, msg=None) | 验证expr是true,如果为false,则fail |
4 | assertFalse(expr,msg=None) | 验证expr是false,如果为true,则fail |
5 | assertIs(arg1, arg2, msg=None) | 验证arg1、arg2是同一个对象,不是则fail |
6 | assertIsNot(arg1, arg2, msg=None) | 验证arg1、arg2不是同一个对象,是则fail |
7 | assertIsNone(expr, msg=None) | 验证expr是None,不是则fail |
8 | assertIsNotNone(expr, msg=None) | 验证expr不是None,是则fail |
9 | assertIn(arg1, arg2, msg=None) | 验证arg1是arg2的子串,不是则fail |
10 | assertNotIn(arg1, arg2, msg=None) | 验证arg1不是arg2的子串,是则fail |
11 | assertIsInstance(obj, cls, msg=None) | 验证obj是cls的实例,不是则fail |
12 | assertNotIsInstance(obj, cls, msg=None) | 验证obj不是cls的实例,是则fail |
1.setupclass里设置self.xxx变量,不同用例之间无法实时共享参数变动
2.setupclass里设置globals().["xxx"]变量,不同用例之间可以实时共享参数变动
3.setupclass里设置 ClassName.XXX变量,不同用例之间可以实时共享参数变动
4.setupclass之前设置 XXX变量
2.setupclass里设置globals().["xxx"]
from settings import *import requests,jsonimport unittestclass Login(unittest.TestCase): @classmethod def setUpClass(self): api_token = '/v1/api/common/getToken' self.real_token_url = API_TEST_BASE_URL + api_token globals()["token"] = None def test_get_token(self): r = requests.post(url=self.real_token_url) globals()["token"] = json.loads(r.text)['model']['token'] print("第一个case获得的token:",globals()["token"]) return globals()["token"] def test_get_u(self): print("第二个case获得token值:",globals()["token"])if __name__ == '__main__': unittest.main()执行结果:第一个case获得的token: 44c5fcccca6c4e64a1c5d314b7ee22fc第二个case获得token值: 44c5fcccca6c4e64a1c5d314b7ee22fc
3.setupclass里设置 ClassName.XXX变量
import unittestclass Mydemo(unittest.TestCase): @classmethod def setUpClass(cls): Mydemo.a = "88" def test1(self): print("test1-----{}".format(Mydemo.a)) Mydemo.a = "99" def test2(self): print("test2-----{}".format(self.a)) print("test2_2---{}".format(Mydemo.a))if __name__ == '__main__': unittest.main()复制代码执行结果:test1-----88test2-----99test2_2---99
4.setupclass之前设置 XXX变量
class AlienTest(unittest.TestCase): status = 200 @classmethod def setUpClass(cls): cls.url = "http://www.baidu.com" globals()['status'] = 300 def test_1_alien(self): print("test_1_status:", self.status) def test_2_alien(self): self.status = 404 print("test_2_status", self.status) def test_4_alien(self): print("test_4_global_status", globals()['status']) print("test_4_status", self.status)if __name__ == '__main__': unittest.main()test_1_status: 200test_2_status 404test_4_global_status 300test_4_status 200
结论: unittest执行测试用例,默认是根据用例的方法名 的 ASCII码的顺序加载测试用例,数字与字母的顺序为:0-9,A-Z,a-z
那么如何控制用例执行顺序呢?
方式1,通过TestSuite类的addTest方法,按顺序加载测试用例
1 # coding=utf-8 2 #1.先设置编码,utf-8可支持中英文,如上,一般放在第一行 3 4 #2.注释:包括记录创建时间,创建人,项目名称。 5 ''' 6 Created on 2019-4-23 7 @author: 北京-宏哥 8 Project:学习和使用unittest框架编写测试用例执行顺序 9 '''10 #3.导入unittest模块11 import unittest12 #4.执行顺序和运行测试13 import unittest14 15 class TestLogin(unittest.TestCase):16 17 def setUp(self):18 pass19 def test_login_blog(self):20 """登录博客园21 22 :return:23 """24 print("登录博客园")25 def test_add_essay(self):26 """ 添加随笔27 28 :return:29 """30 print("添加随笔")31 def test_release_essay(self):32 """ 发布随笔33 34 :return:35 """36 print("发布随笔")37 def test_quit_blog(self):38 """退出博客园39 40 :return:41 """42 print("退出博客园")43 44 def tearDown(self):45 pass46 if __name__ == '__main__':47 # 启动单元测试48 # unittest.main()49 50 # 获取TestSuite的实例对象51 suite = unittest.TestSuite()52 53 # 将测试用例添加到测试容器中54 suite.addTest(TestLogin('test_login_blog'))55 suite.addTest(TestLogin('test_add_essay'))56 suite.addTest(TestLogin('test_release_essay'))57 suite.addTest(TestLogin('test_quit_blog'))58 59 # 创建TextTestRunner类的实例对象60 runner = unittest.TextTestRunner()61 runner.run(suite)62 #unittest.TextTestRunner(verbosity=3).run(suite)
方式2,通过修改函数名的方式
1 # coding=utf-8 2 #1.先设置编码,utf-8可支持中英文,如上,一般放在第一行 3 4 #2.注释:包括记录创建时间,创建人,项目名称。 5 ''' 6 Created on 2019-4-23 7 @author: 北京-宏哥 8 Project:学习和使用unittest框架编写测试用例执行顺序 9 '''10 #3.导入unittest模块11 import unittest12 #4.执行顺序和运行测试13 import unittest14 15 class TestLogin(unittest.TestCase):16 17 def setUp(self):18 pass19 def test_1_login_blog(self):20 """登录博客园21 22 :return:23 """24 print("登录博客园")25 def test_2_add_essay(self):26 """ 添加随笔27 28 :return:29 """30 print("添加随笔")31 def test_3_release_essay(self):32 """ 发布随笔33 34 :return:35 """36 print("发布随笔")37 def test_4_quit_blog(self):38 """退出博客园39 40 :return:41 """42 print("退出博客园")43 44 def tearDown(self):45 pass46 if __name__ == '__main__':47 # 启动单元测试48 unittest.main()
@
unittest.
skip
(reason) 无条件跳过用例,reason是说明原因
@
unittest.
skipIf
(condition, reason) condition为true的时候跳过
@unittest.skipUnless(condition, reason) condition为False的时候跳过
@
unittest.
expectedFailure
(Mark the test as an expected failure. If the test fails when run, the test is not counted as a failure.)将测试标记为预期的失败。 如果测试在运行时失败,则该测试不算作失败。
断言的时候跳过(暂时不知道有啥用,没看懂,貌似断言失败,也变成用例pass了。)
1、下载HTMLTestRunner报告(只是一个py文件),
2、将该文件保存在python安装路径下的lib文件夹中。在文件中能import HTMLTestRunner成功,即配置成功
注意:
在python3中用HTMLTestRunner.py报importError“:No module named 'StringIO'解决办法
原因是官网的是python2语法写的,看官手动把官网的HTMLTestRunner.py改成python3的语法。
第94行,将import StringIO修改成import io第539行,将self.outputBuffer = StringIO.StringIO()修改成self.outputBuffer = io.StringIO()第642行,将if not rmap.has_key(cls):修改成if not cls in rmap:第631行,将print >> sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)修改成print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))第766行,将uo = o.decode('latin-1')修改成uo = e 第772行,将ue = e.decode('latin-1')修改成ue = e
生成报告的代码:
import unittestimport HTMLTestRunnerclass TestDemo001(unittest.TestCase): @classmethod def setUpClass(cls): print("====setup========") globals()["abc"] = "111" @classmethod def tearDownClass(cls): print("=====tearDown======") def test_002(self): print("======test002======") res = "1001" print("globals()[\"abc\"]===", globals()["abc"]) #self.assertEqual(res,"1001","测试成功") def test_001(self): print("======test001====") res = "1000" print("globals()[\"abc\"]===",globals()["abc"]) #self.assertEqual(res, "1001", "测试成功") @unittest.skip("test_bw") def test_000(self): print("======000====") globals()["abc"] = "000" print("globals()[\"abc\"]===", globals()["abc"])if __name__ == "__main__": #unittest.main() suite = unittest.TestSuite() suite.addTest(TestDemo001("test_001")) suite.addTest(TestDemo001("test_002")) filepath = "../report/demo001.html" f = open(filepath,"wb") run = HTMLTestRunner.HTMLTestRunner(stream=f,title="这是一个demo001测试报告") run.run(suite)
该方法适用于以下条件:
1.运行测试用例一切正常,只是没有测试报告显示
2.使用命令行pyhon 脚本名字.py 却可以生成测试报告
pycharm 在运行测试用例的时候 默认是以unittest 框架来运行的,所以不能生成测试报告
如何判断是否是用unitest框架运行的呢?
运行完成后,如果发现右上角有unittest in ***** ,说明是以框架的方式来运行的
设置运行方式如已下步骤,设置完成后,再运行就能够生产报告了
1、如何使用python开发测试框架?
python开发,request进行网络请求,unnitest管理case(断言,跳过),生成测试报告(HTMLTestRunner),数据的存储,持续集成(批处理文件),
2、如何管理case
两个case之间有依赖:skip,case写在excel
3.简述case的执行
case的执行顺序
4.如何解决case的依赖
全局变量
5.如何生成测试报告
HTMLTesTRunner