一、认识unittest
1.认识单元测试
class Calculator:
def __init__(self, a, b):
self.a = a
self.b = b
def add(self):
return self.a + self.b
def sub(self):
return self.a - self.b
def mul(self):
return self.a * self.b
def div(self):
return self.a / self.b
import unittest
from calculator import Calculator
# 创建一个测试类必须要继承unittest模块的TestCase类
class MyTestCase(unittest.TestCase):
# 创建一个测试方法必须以test开头
def test_add(self):
c = Calculator(3, 5)
result = c.add()
self.assertEqual(result, 8)
def test_sub(self):
c = Calculator(3, 5)
result = c.sub()
self.assertEqual(result, -2)
def test_mul(self):
c = Calculator(3, 5)
result = c.mul()
self.assertEqual(result, 10)
def test_div(self):
c = Calculator(10, 5)
result = c.div()
self.assertEqual(result, 2)
if __name__ == '__main__':
unittest.main()
2.重要概念
2.1 Test Case
是最小的测试单元,用于检查特定输入集合的特定返回值。unittest提供了TestCase基类。
2.2 Test Suite
测试套件是测试用例、测试套件或两者的集合,用于组装一组要运行的测试。unittest提供了TestSuite类来创建测试套件。
2.3 Test Runner
是一个组件,用于协调测试的执行并向用户提供结果。unittest提供了TextTestRunner类运行测试用例。
2.4 Test Fixture
代表执行一个或多个测试所需的环境设备,以及关联的清理动作。
import unittest
from calculator import Calculator
# 创建一个测试类必须要继承unittest模块的TestCase类
class TestCalculator(unittest.TestCase):
# 测试用例的前置动作
def setUp(self):
print("test start:")
# 测试用例的后置动作
def tearDown(self):
print("test end")
# 创建一个测试方法必须以test开头
def test_add(self):
c = Calculator(3, 5)
result = c.add()
self.assertEqual(result, 8)
def test_sub(self):
c = Calculator(3, 5)
result = c.sub()
self.assertEqual(result, -2)
def test_mul(self):
c = Calculator(3, 5)
result = c.mul()
self.assertEqual(result, 10)
def test_div(self):
c = Calculator(10, 5)
result = c.div()
self.assertEqual(result, 2)
if __name__ == '__main__':
# 创建测试套件
suit = unittest.TestSuite()
suit.addTest(TestCalculator("test_add"))
suit.addTest(TestCalculator("test_sub"))
suit.addTest(TestCalculator("test_mul"))
suit.addTest(TestCalculator("test_div"))
# 创建测试运行程序
runner = unittest.TextTestRunner()
runner.run(suit)
3.断言方法
import unittest
class TestAssert(unittest.TestCase):
def test_equal(self):
self.assertEqual(2+2, 4)
self.assertEqual("python", "python")
self.assertNotEqual("hello", "love")
def test_in(self):
self.assertIn("hello", "hello world")
self.assertNotIn("hi", "hello")
def test_true(self):
self.assertTrue(True)
self.assertFalse(False)
if __name__ == '__main__':
unittest.main()
4.测试用例的组织与discover方法
class LeapYear:
def __init__(self, year):
self.year = year
def answer(self):
year = self.year
if year % 100 == 0:
if year % 400 == 0:
return "{0}是闰年".format(year)
else:
return "{0}不是闰年".format(year)
else:
if year % 4 == 0:
return "{0}是闰年".format(year)
else:
return "{0}不是闰年".format(year)
import unittest
from leapyear import LeapYear
class TestLeapYear(unittest.TestCase):
def test_2000(self):
ly = LeapYear(2000)
self.assertEqual(ly.answer(), "2000是闰年")
def test_2001(self):
ly = LeapYear(2001)
self.assertEqual(ly.answer(), "2001是闰年")
if __name__ == "__main__":
unittest.main()
import unittest
# 定义测试用例的目录为当前目录中的test_case目录
test_dir = './test_case'
suits = unittest.defaultTestLoader.discover(test_dir, pattern='test*.py')
if __name__ == "__main__":
runner = unittest.TextTestRunner()
runner.run(suits)
二、关于unittest
1. 测试用例的执行顺序
unittest默认根据ASCII码的顺序加载测试用例(0~9,A~Z,a~z),可以通过使用套件来控制。
2.执行多级目录的测试用例
discover()方法只能加载写在方法里的目录的用例,可以通过给每个子目录下放一个__init__.py文件将一个子目录标记成一个标准的Python模块。
3.跳过测试和预期失败
import unittest
class MyTest(unittest.TestCase):
@unittest.skip("直接跳过测试")
def test_skip(self):
print("aaa")
@unittest.skipIf(3 > 2, "当条件为真时跳过测试")
def test_skip_if(self):
print("bbb")
@unittest.skipUnless(3 > 2, "当条件为真时执行测试")
def test_skip_unless(self):
print("ccc")
# 不管执行结果如何都会标记失败,但不会抛出失败信息
@unittest.expectedFailure
def test_expect_failure(self):
self.assertEqual(2, 3)
if __name__ == "__main__":
unittest.main()
4.Fixture
即setUp/tearDown,还有测试类和模块的Fixture
import unittest
def setUpModule():
print("test Module start >>>>>")
def tearDownModule():
print("test module end >>>>>")
class MyTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("test class start >>>>>")
@classmethod
def tearDownClass(cls):
print("test class end >>>>>")
def setUp(self):
print("test case start >>>>>")
def tearDown(self):
print("test case end >>>>>")
def test_case1(self):
print("case1")
def test_case2(self):
print("case2")
if __name__ == "__main__":
unittest.main()
三、编写Web自动化测试
import unittest
from time import sleep
from selenium import webdriver
class TestBaidu(unittest.TestCase):
# 可以避免多次打开浏览器
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome()
cls.base_url = "https://www.baidu.com"
# 不是用例不会执行
def baidu_search(self, search_key):
self.driver.get(self.base_url)
self.driver.find_element_by_id("kw").send_keys(search_key)
self.driver.find_element_by_id("su").click()
sleep(2)
def test_search_key_selenium(self):
search_key = "selenium"
self.baidu_search(search_key)
self.assertEqual(self.driver.title, search_key+"_百度搜索")
def test_search_unittest(self):
search_key = "unittest"
self.baidu_search(search_key)
self.assertEqual(self.driver.title, search_key+"_百度搜索")
@classmethod
def tearDownClass(cls):
cls.driver.quit()
if __name__ == "__main__":
unittest.main()