unittest框架

一、unitest简介

unittest(在Python中通常写作unittest,注意大小写)是Python自带的一个强大的单元测试框架。

Unittest框架四大组件:
1、TestCase 测试用例
2、TestFixture
3、TestSuite
4、TestRunner

二、unittest的四大组件

2.1 TestCase 测试用例

unittest中TestCase部分的规则:
1、用例类必须继承Unittest.TestCase,并且以test开头
2、每条用例,都必须以test开头
3、用例执行的顺序按照ASCII: 0-9 a-z A-Z 顺序来执行用例

unittest也可以通过命令运行
命令执行TestShopnc类下的所有用例: python -m unittest 用例文件名.用例类
执行某一条用例: python -m unittest 用例文件名.用例类.用例名称
python -m unittest test_case.TestShop.test_login

import unittest


class TestShop(unittest.TestCase):

    def test_login(self):
        print("测试 01")

    def test_shopping(self):
        print("测试 02")

    def test_payment(self):
        print("测试 03")


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

2.2 TestFixture 测试夹具

测试夹具 执行测试用例前的前置操作及后置操作

    def setUp(self) -> None:
        """
        前置操作,  setUp执行每条用例前都会执行函数代码,有n条用例,则会执行n次
        :return:
        """
        # 加载项目,打开浏览器之类的操作
        self.driver = webdriver.Chrome()
        self.driver.get("http://www.baidu.com")
        ele = self.driver.find_element(By.ID, "kw")
        self.driver.maximize_window()
        ele.send_keys("王勇")
        time.sleep(3)

    @classmethod
    def setUpClass(cls) -> None:
        """
        前置操作  setUpClass执行用例前会执行 ,总共只执行一次
        :return:
        """
        # 链接数据库,连接数据, 打开浏览器
        pass

    def tearDown(self) -> None:
        """
        后置操作, tearDown执行完每条用例前都会执行代码,有n条用例,则会执行n次
        :return:
        """
        # 
        self.driver.close()

    @classmethod
    def tearDownClass(cls) -> None:
        """
        后置操作  tearDownClass执行完所有用例之后会执行代码 ,总共只执行一次
        :return:
        """
        cls.driver.quit()

 

2.3 TestSuite 测试套件(测试用例集)

2.3.1 一次添加单个用例(addTest)

# 测试套件 用例集(把需要执行的用例汇总到一起)

import unittest


class TestShop(unittest.TestCase):

    def test_login(self):
        print("测试 01")

    def test_shopping(self):
        print("测试 02")

    def test_payment(self):
        print("测试 03")


if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTest(TestShop("test_login"))
    suite.addTest(TestShop("test_payment"))
    unittest.main(defaultTest="suite")

2.3.2 一次添加多个用例(addTests)

import unittest


class TestShop(unittest.TestCase):

    def test_login(self):
        print("测试 01")

    def test_shopping(self):
        print("测试 02")

    def test_payment(self):
        print("测试 03")


if __name__ == '__main__':

    suite = unittest.TestSuite()
    case_list = [TestShop("test_login"), TestShop("test_payment")]
    suite.addTests(case_list)
    unittest.main(defaultTest="suite")

2.3.3 用例加载器(loadTestsFromTestCase)

# 和 unittest.main() 基本上就是一样的

import unittest


class TestShop(unittest.TestCase):

    def test_login(self):
        print("测试 01")

    def test_shopping(self):
        print("测试 02")

    def test_payment(self):
        print("测试 03")


if __name__ == '__main__':
    suite = unittest.TestSuite()
    # 用例加载器  # 用例 TestLoader() suite
    # loadTestsFromTestCase 加载某个用例类(继承 TestCase)下的所有用例
    test_cases = unittest.TestLoader().loadTestsFromTestCase(TestShop)
    suite.addTests(test_cases)
    unittest.main(defaultTest="suite")

2.3.4 利用默认加载器实现加载用例(defaultTestLoader)

import unittest


class TestShop(unittest.TestCase):

    def test_login(self):
        print("测试 01")

    def test_shopping(self):
        print("测试 02")

    def test_payment(self):
        print("测试 03")


if __name__ == '__main__':
    suite = unittest.TestSuite()
    # discover(文件夹, 以..开头的文件(默认是test*.py))
    test_dir = "../unittest_study"
    unittest.defaultTestLoader.discover(test_dir)
    unittest.main(defaultTest="suite")

2.4 TestRunner 测试运行器,生成测试报告

测试运行器 执行用例,把执行的结果输出给到用户
用例执行结果状态:
. 用例执行成功
E 用例有异常
F 用例执行失败(断言失败)

企业测试报告的优化及定制 优化测试报告模板 通过js+html/html5
pytest+allure 生成更加美观的测试报告+优化定制(装饰器)

2.4.1 TextTestRunner 生成文本格式测试报告

unittest 提供生成测试报告的模块   TextTestRunner 生成文本格式测试报告

# test_case.py

import time
import unittest


class TestShop(unittest.TestCase):

    def test_login(self):
        print("测试 01")

    def test_shopping(self):
        print("测试 02")

    def test_payment(self):
        print("测试 03")
import unittest
from Code.unittest_study.test_case import TestShop

# 加载用例
testcases = unittest.TestLoader().loadTestsFromTestCase(TestShop)
# 执行用例,生成测试报告
with open("report/report.text", "w") as f:
    unittest.TextTestRunner(stream=f, verbosity=2).run(testcases)  # 1 简介   2 详细一点
; 生成的结果 report.text
test_login (Code.unittest_study.test_case.TestShop) ... ok
test_payment (Code.unittest_study.test_case.TestShop) ... ok
test_shopping (Code.unittest_study.test_case.TestShop) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

2.4.2 结合unittest生产html格式测试报告

HtmlTestRunner: https://www.cnblogs.com/wangyong123/articles/18431254
1. 官网下载HtmlTestRunner.py只能支持python2版本,支持Python3,需要做修改
2. python安装路径/Lib

# test_case.py

import time
import unittest


class TestShop(unittest.TestCase):

    def test_login(self):
        print("测试 01")

    def test_shopping(self):
        print("测试 02")

    def test_payment(self):
        print("测试 03")
import unittest
import HTMLTestRunner
from Code.unittest_study.test_case import TestShop

# 加载用例
testcases = unittest.TestLoader().loadTestsFromTestCase(TestShop)
# 执行用例,生成测试报告
with open("report/report.html", "wb+") as f:
    runner = HTMLTestRunner.HTMLTestRunner(stream=f, title="report.html", description="测试结果描述")
    runner.run(testcases)

2.4.3 BeatifulReport 生成测试报告

# test_case.py

import time
import unittest


class TestShop(unittest.TestCase):

    def test_login(self):
        print("测试 01")

    def test_shopping(self):
        print("测试 02")

    def test_payment(self):
        print("测试 03")
import unittest
from BeautifulReport import BeautifulReport
from Code.unittest_study.test_case import TestShop

# 加载用例
testcases = unittest.TestLoader().loadTestsFromTestCase(TestShop)
# 执行用例,生成测试报告
with open("report/report_bf.html", "wb+") as f:
    BeautifulReport(testcases).report(description="测试结果描述", filename="report_bf", report_dir="./report")

三、装饰器 @ unittest.skip 强制跳过&条件跳过

@unittest.skip 强制跳过执行
@unittest.skipIf 符合条件,则跳过执行
@unittest.skipUnless 条件不成立,则跳过执行

在类中加,那么可以直接跳过整个类

import time
import unittest


# @unittest.skip("整个用例类都不执行")
# @unittest.skipIf(True, "整个用例类都不执行")
@unittest.skipUnless(False, "整个用例类都不执行")
class TestShopSkip(unittest.TestCase):
    def test_login(self):
        print("skip 测试 01")

    def test_shopping(self):
        print("skip 测试 02")

    def test_payment(self):
        print("skip 测试 03")


class TestShop(unittest.TestCase):

    def test_login(self):
        print("测试 01")

    @unittest.skip("此用例暂时不启用")
    def test_shopping(self):
        print("测试 02")

    # @unittest.skipIf("条件1", "条件为真,则跳过")
    @unittest.skipIf(3 > 2, "条件为真,则跳过")
    def test_payment(self):
        print("测试 03")

    @unittest.skipUnless(2 > 3, "2>3不成立,则跳过执行")
    def test_select_goods(self):
        print("测试 04")


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

四、unittest的常用断言方法

assertIn(字符1,字符2)  # 字符1是否包含在字符2
self.assertNotIn(字符1,字符2)  # 字符1不包含包含在字符2
self.assertEqual(参数1,参数2,"断言失败的描述")  # 参数1等于参数2
self.assertNotEqual(参数1,参数2,"断言失败的描述")  # 参数不等于参数2
self.assertTrue(True)
self.assertFalse(False)
import time
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By


class TestShop(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        """
        前置操作
        :return:
        """
        # 打开浏览器
        cls.driver = webdriver.Chrome()

    @unittest.skip("跳过登录")
    def test_login(self):
        """
        登录
        :return:
        """
        print("登录")

    def test_select_goods(self):
        """
        搜索商品
        :return:
        """
        self.driver.get("http://101.34.221.219:8010/")
        ele_select = self.driver.find_element(By.ID, "search-input")
        select_good = "手机"
        ele_select.send_keys(select_good)
        ele_button = self.driver.find_element(By.ID, "ai-topsearch")
        ele_button.click()
        time.sleep(3)
        # 断言:验证测试结果与预期结果是否一致
        # 获取商品列表的标题
        ele_content = self.driver.find_element(By.XPATH, "//ul/li[1]/div/a[1]/div[@class='am-padding-xs']/p")
        text = ele_content.text
        # 断言是否含有手机
        self.assertIn(select_good, text, "商品未包含检索内容")

    def tearDown(self) -> None:
        self.driver.close()

    @classmethod
    def tearDownClass(cls) -> None:
        cls.driver.quit()


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

 

posted on 2024-09-20 07:24  软饭攻城狮  阅读(20)  评论(0编辑  收藏  举报

导航