内部UI自动化测试培训之unittest基础
这个文档的由来是公司内部UI自动化测试培训的资料。部门为了减少测试工作量,准备做UI自动化测试。我写python,其他同事都是java,所以python基础和UI自动化测试selenium的培训就由我来完成。本篇是单元测试工具uniitest的基础介绍。
UI 自动化测试相关内容:
unittest 介绍
Unittest是Python内部自带的一个单元测试的模块,它设计的灵感来源于Junit,具有和Junit类似的结构,有过Junit经验的朋友可以很快上手。它可以做单元测试, 也能用于编写和运行重复的测试工作。
它给自动化测试用例开发和执行提供了丰富的断言方法, 判断测试用例是否通过, 并最终生成测试结果。
TestCase 测试用例编写
unittest 基本知识包括如下:
- TestCase指的就是测试用例
- 测试类必须继承unittest.TestCase
- 测试方法名称命名必须以test开头
- 测试方法的执行顺序由Case序号决定, 并非由代码顺序决定
# 1. 导入unittest
import unittest
# 2. 创建类继承unittest.TestCase
class TestDemo(unittest.TestCase):
# 3. 创建测试用例方法, 方法要以test开头
# 执行顺序是根据case序号来的, 并非代码的顺序
def test_add_01(self):
print(3+2)
assert 3+2 == 5
def test_add_02(self):
print(5+5)
assert 5+5 == 10
if __name__ == '__main__':
unittest.main()
(dev) ➜ ui_test python unittest_demo.py
5
.10
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
unittest 特性
unittest 测试类中有一些特殊方法可以方便单元测试的环境准备和结束收尾,下面分别介绍。
单个测试用例
一个测试用例就是类似中的一个方法,启动一个测试用例可能需要准备参数,准备环境。以下两个方法可以用于当前场景:
- setUp 初始化测试环境, 它在每条测试用例执行前都会调用
- tearDown 测试用例执行完毕后恢复测试环境, 即使出现异常也会调用此方法,每条用例执行结束后都会运行
import unittest
class Test(unittest.TestCase):
def setUp(self) -> None: # 调用setUp
super().setUp()
print("测试用例执行前操作")
def test_add_01(self):
print("num02")
def test_add_02(self):
print("num03")
def tearDown(self) -> None: # 调用tearDown
super().tearDown()
print("测试用例执行后操作")
if __name__ == '__main__':
unittest.main()
(idt_dev) ➜ ui_auto_test python unittest_demo.py
测试用例执行前操作
num02
测试用例执行后操作
.测试用例执行前操作
num03
测试用例执行后操作
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
setUp 和 tearDown 会在每一个测试用例执行时生效,setUp在用例执行前执行,tearDown在用户执行后执行。
全局测试用例
在所有测试用例执行前可能也会需要一些初始化工作,如果能完成就可以避免在单个用例中重复工作。而 setUpClass 和 tearDownClass 可以完成相关工作。
- setUpClass 初始化测试环境且只会执行一次。在类中需要加上@classmethod
- tearDownClass 恢复测试环境且只会执行一次。在类中需要加上@classmethod
import unittest
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
print("测试前的操作")
@classmethod
def tearDownClass(cls) -> None:
super().tearDownClass()
print("测试后的操作")
def test_add_01(self):
print("num01")
def test_add_02(self):
print("num02")
if __name__ == '__main__':
unittest.main()
测试前的操作
num01
.num02
.测试后的操作
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
在所有测试用例之前会执行setUpClass,而且只会执行一次。所有测试用例执行完成之后执行tearDownClass,同样只会执行一次。
断言表达式
断言表达式用于检测一个变量是否符合预期,常见的断言表达式如下:
断言表达式
示例如下:
import unittest
class Test(unittest.TestCase):
def setUp(self) -> None:
super().setUp()
print("测试开始")
def test_add_01(self):
print("1 == 1")
self.assertEqual(1, 1) # 成功
def test_add_02(self):
print("1 == 2")
self.assertEqual(1, 2) # 失败
def test_add_03(self):
print("x is True")
self.assertTrue(True) # 成功
def test_add_04(self):
print("x is False")
self.assertFalse(False) # 失败
def test_add_05(self):
print("a in b")
self.assertIn(1, [1,2,3]) # 成功
def test_add_06(self):
print("a not in b")
self.assertNotIn(1, [1,2,3]) # 失败
def tearDown(self) -> None:
super().tearDown()
print("测试结束")
if __name__ == '__main__':
unittest.main()
测试开始
1 == 1
测试结束
.测试开始
1 == 2
测试结束
F测试开始
x is True
测试结束
.测试开始
x is False
测试结束
.测试开始
a in b
测试结束
.测试开始
a not in b
测试结束
F
======================================================================
FAIL: test_add_02 (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "unittest_demo.py", line 15, in test_add_02
self.assertEqual(1, 2) # 失败
AssertionError: 1 != 2
======================================================================
FAIL: test_add_06 (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "unittest_demo.py", line 31, in test_add_06
self.assertNotIn(1, [1,2,3]) # 失败
AssertionError: 1 unexpectedly found in [1, 2, 3]
----------------------------------------------------------------------
Ran 6 tests in 0.000s
FAILED (failures=2)
测试工程
单元测试是一个工程,由多个python文件组成的,工程的代码组织应该有一个清晰的规范。规范如下:
- 创建一个包保存所有的文件
- 一个主入口执行所有单元测试
结构如下:
test_1.py
import unittest
class Test(unittest.TestCase):
def setUp(self) -> None:
super().setUp()
print("测试开始")
def test_add_01(self):
print("1 == 1")
self.assertEqual(1, 1)
def test_add_02(self):
print("1 == 2")
self.assertEqual(1, 2)
def tearDown(self) -> None:
super().tearDown()
print("测试结束")
test_2.py
import unittest
class Test(unittest.TestCase):
def setUp(self) -> None:
super().setUp()
print("测试开始")
def test_add_03(self):
print("x is True")
self.assertTrue(True)
def test_add_04(self):
print("x is False")
self.assertFalse(False)
def tearDown(self) -> None:
super().tearDown()
print("测试结束")
test_main.py
import unittest
# dicsover方法查找用例
suite = unittest.defaultTestLoader.discover("unittest_demo", "test*.py")
# 2.TextTestRunner运行用例
runer = unittest.TextTestRunner()
runer.run(suite)
运行结果:
测试开始
1 == 1
测试结束
.测试开始
1 == 2
测试结束
F测试开始
x is True
测试结束
.测试开始
x is False
测试结束
.
======================================================================
FAIL: test_add_02 (test_1.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/ljk/Documents/code/python-dev/ui_auto_test/unittest_demo/test_1.py", line 15, in test_add_02
self.assertEqual(1, 2)
AssertionError: 1 != 2
----------------------------------------------------------------------
Ran 4 tests in 0.000s
FAILED (failures=1)
selenium + unittest 完整示例
import time
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By
class MyTestCase(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome() # 初始化浏览器驱动
def test_baidu_search(self):
# 打开百度首页
self.driver.get("https://www.baidu.com")
# 断言页面标题是否包含"百度一下"
self.assertIn("百度一下", self.driver.title)
# 找到搜索框并填充内容
search_input = self.driver.find_element(By.NAME, "wd")
search_query = "python selenium"
search_input.send_keys(search_query)
time.sleep(6)
search_input.submit()
self.driver.implicitly_wait(5)
# 定位搜索结果元素
search_results = self.driver.find_elements(By.CSS_SELECTOR, ".result.c-container")
for result in search_results:
print(result.text)
# 断言搜索结果是否显示
self.assertTrue(search_results)
def tearDown(self):
self.driver.quit() # 关闭浏览器驱动
if __name__ == '__main__':
unittest.main()