您的位置:首页 > 编程语言 > Python开发

python自动化测试框架unittest

2020-07-14 04:53 459 查看

首先要明白什么是框架:
首先框架中可以为后续扩展的组件提供很多辅助性、支撑性的方便易用的工具,也就是说框架是配套了一些帮助解决某类问题的库(libraries)或工具(tools)。
框架本身一般不完整到可以解决特定问题;另外框架天生就是为扩展而设计的;
其次再补充几个关于unittest定义
断言: 类似测试用例中的期望结果,在执行自动化脚本的时候,使用断言进行期望结果与实际运行结果的对比进行功能验证。测试业务需要验证多少功能,那就在自动化脚本添加多少断言。
测试脚手架: 执行测试之前或者执行测试之后要做的一些操作。比如测试完成之后清理垃圾数据,测试完成之后关闭浏览器。
测试用例集: 多个测试用按照功能的划分放在一起,测试用例集。
测试运行器:执行测试用例。
编码规范
1.使用unittest作为单元测试框架需要继承 unittest.TestCase 类
2.类中测试方法名以 test开始
3.执行TestCase 顺序 <不是安装定义testcase 的先后顺序去执行,而是按照方法名的顺序执行>排序方式 是按照0-9,A-Z,a-z ,_ 命名顺序执行。

来一段unittest框架测试登录的代码

import unittest
from selenium import webdriver
from po.navbar import NavBar

# 继承 unittest.TestCase
class TestLogin(unittest.TestCase):

def test_login(self):
"""
测试用户登录
:return:
"""
# 1. 打开浏览器
driver = webdriver.Chrome()
# 2. 打开网站首页
driver.get("http://39.107.96.138:3000/")
# 3. 导航到登录页面
navBar = NavBar(driver)
loginPage = navBar.go_to_login_page()
# 4. 使用正确的用户名和密码登录
loginPage.login_with_username_pass(username="imtest11",passwd="123456")
# 5.1 登录成功 期望页面能够跳转到首页
url = driver.current_url
self.assertEqual(url,'http://39.107.96.138:3000/')
# 5.2 登录成功 期望首页页面上个人信息栏中 imtest11 用户名
username = driver.find_element_by_css_selector('span[class="user_name"]>a.dark').text
self.assertEqual(username,'imtest11')

if __name__ == '__main__':
unittest.main()

其实在每次执行testcase的时候会有种种相同的前提或后续操作,这时候便引入了另外一个概念:测试脚手架(前面已给出定义)
首先就是里面的
1.setUpClass
定义所有的cases运行之前执行的操作。 比如一个文件中有多个case ,每个case都需要打开浏览器操作,那么就可以将打开浏览器操作放在 setUpClass 中。

@classmethod#setUpClass() 为类方法,所以要加上 @classmethod 装饰器。
def setUpClass(cls) -> None:
"""
运行所有的用例之前执行
:return:
"""
# 1. 打开浏览器
cls.driver = webdriver.Chrome()
# 2. 打开首页
cls.driver.get("http://39.107.96.138:3000/")

2.tearDownClass
定义所有的cases运行之后执行的操作。 比如Web自动化中,运行完成所有的cases之后,要将浏览器关闭,那么关闭浏览器操作可以定义在 tearDownClass 中。

@classmethod
def tearDownClass(cls) -> None:
"""
所有的用例执行完成之后
:return:
"""
cls.driver.quit()

3.setUp
每一个case运行之前执行

def setUp(self) -> None:
"""
每一个TestCase 执行之前的操作
:return:
"""
# 删除所有的cookies
self.driver.delete_all_cookies()
self.driver.get("http://39.107.96.138:3000/")

4.setDown
每一个case运行之后执行

def tearDown(self) -> None:
"""
每一个case 运行之后的操作
:return:
"""
# TODO 将截图文件放到 screenshots 目录下,要求如下:
# 1. 以当前日期为图片的文件 日期格式 2020-05-17_14_32_29.png
# 2. 图片格式为png格式
self.driver.save_screenshot('01.png')
suite = unittest.TestSuite()

主要方法有两个
addTest() 每次添加单个测试用例到测试套件中
addTests() 添加多个测试用例
添加单个:

import unittest
from testcases.test_login import TestLogin
from testcases.test_register import TestResgiter

def suite():
testsuite = unittest.TestSuite()  # 创建测试套件
# addTest 方法添加单个测试用例 格式:  类名('方法名')
# 使用addTest的方式只适合小型测试场景。同时用很多个测试用例 就不太适合了。
testsuite.addTest(TestLogin('test_login'))  # TestLogin中 test_login的测试方法
testsuite.addTest(TestResgiter('test_register')) # TestLogin中 test_register的测试方法
return testsuite

添加多个测试用例使用unittest中 TestLoader() 类可以帮助我们加载多个测试用例。
主要使用方法有:
loadTestsFromTestCase
loadTestsFromModule
loadTestsFromName
discover
1.loadTestsFromTestCase使用测试此方法是需要传入 类名, loader能够自动解析此类名中所有的test case

import unittest
from testcases.test_login import TestLogin
from testcases.test_register import TestResgiter

def suite2():
"""
当测试用例文件特别多的时候, 使用 TestLoader 搜寻Testcase
:return:
"""
suite =unittest.TestSuite()
loader = unittest.TestLoader()
# 从类中加载所有的测试用例 loadTestsFromTestCase 格式: 传入 类名
testlogins = loader.loadTestsFromTestCase(TestLogin) # 从TestLogin类中加载
testregisters = loader.loadTestsFromTestCase(TestResgiter) 从TestRegister类中加载
suite.addTests(testlogins)
suite.addTests(testregisters)

return suite

2.loadTestsFromModule从模块中进行加载

import tmp.tmp1 as t1
import tmp.tmp2 as t2

def suite():
suite = unittest.TestSuite()

loader = unittest.TestLoader()
# 从py文件中添加所有测试用用例 模块路径
tests1 = loader.loadTestsFromModule(t1)
tests2 = loader.loadTestsFromModule(t2)

suite.addTests(tests1)
suite.addTests(tests2)

return suite

t1,t2 分别为两个python的模块文件,可以从模块中加载。t1,t2 文件内容详见 https://gitee.com/imzack/webapp/tree/master/tmp

3.loadTestsFromName如果想自由的加载模块或者类或者方法,可以使用此方法。

def suite2():
suite = unittest.TestSuite()
loader = unittest.TestLoader()
# 给定一个测试路径的名称  tmp.tmp1.TestA.testA_01  加载TestA中的 testA_01 一个方法
tests1 = loader.loadTestsFromName('tmp.tmp1.TestA.testA_01')
suite.addTests(tests1)
return suite

tmp.tmp1.TestA.testA_01 为 加载TestA中的 testA_01方法,如果想加载整个 TestA类,

loader.loadTestsFromName('tmp.tmp1.TestA')

4.discover探索模式,给定目录,从目录中搜索所有的符合条件的用例

def suite3():
suite = unittest.TestSuite()
loader = unittest.TestLoader()
# discover 探索模式,给定目录,从目录中搜索所有的符合条件的用例
tests = loader.discover('tmp',pattern='tmp*.py')
suite.addTests(tests)
return suite

加载 tmp目录下所有以tmp开头的py文件。

跳过测试测试用例中可以使用 unittest 内置的skip装饰器跳过运行某个测试方法。
skip
skipIf
skipUnless

class TestC(unittest.TestCase):

@unittest.skip('跳过这个用例')
def testC_01(self):
self.assertTrue(True)

@unittest.skipUnless(sys.platform.startswith('win'),'Windows系统才能运行')
def testC_02(self):
self.assertTrue(True)

测试执行器
TextTestRunner() 为unittest内置的测试执行器,负责运行测试套件中所有的测试用例。运行的是调用run方法可以执行。

if __name__ == '__main__':
runner = unittest.TextTestRunner()  # 用例执行器
suite = suite2()
runner.run(suite) # 运行测试套件

run() 执行默认生成测试结果只在命令行窗口中显示,关闭命令行窗口,那么测试结果就不复存在了。

将测试结果保存到文件中
更改TextTestRunner类 中 stream 字段可以实现写入文件操作

if __name__ == '__main__':
suite = suite3()
with open('report.txt',mode='w',encoding='utf8') as f:
runner = unittest.TextTestRunner(stream=f , verbosity=2)
runner.run(suite)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: