内部UI自动化测试培训之unittest基础

image

这个文档的由来是公司内部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文件组成的,工程的代码组织应该有一个清晰的规范。规范如下:

  1. 创建一个包保存所有的文件
  2. 一个主入口执行所有单元测试
    结构如下:

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()
posted @ 2024-03-07 21:22  金色旭光  阅读(59)  评论(0编辑  收藏  举报