自动化测试-selenium-3(unittest单元测试框架)

unittest单元测试框架

一、unittest单元测试框架

1、unittest 是python 的单元测试框架,unittest 单元测试提供了创建测试用例,测试套件以及批量执行的方案, unittest 在安装pyhton 以后就直接自带了,直接import unittest 就可以使用。

2、利用单元测试框架,创建一个类,该类继承unittest的TestCase,将每个case看成是一个最小的单元, 由测试容器组织起来,之后直接执行,同时引入测试报告。

3、unittest 各组件的关系:

在这里插入图片描述

  • test fixture:初始化和清理测试环境,比如创建临时的数据库,文件和目录等,其中 setUp() 和 tearDown()是最常用的方法。
  • test case:单元测试用例,TestCase 是编写单元测试用例最常用的类。
  • test suite:单元测试用例的集合,TestSuite 是最常用的类。
  • test runner:执行单元测试。
  • test report:生成测试报告。
二、批量执行脚本
1、构建测试套件

​ 在unittest中是用TestSuite 类来表示测试用例集、生成测试套件,使用该类的构造函数可以生成一个测试套件的实例。

  • addTest() :将测试用例添加到测试套件中;<一次存放一个测试脚本里一个类的一个方法>

  • makeSuite():将测试用例类内所有的测试case组成测试套件TestSuite,unittest调用makeSuite的时候,只需将测试类名传入即可;<一次存放一个测试脚本中一个类的所有方法>

  • TestLoader用于创建类和模块的测试套件,使用TestLoader().loadTestsFromTestCase(TestClass)来加载测试类;<一次存放一个测试脚本的一个类的所有方法>

  • discover():通过递归的方式到其子目录并从指定的目录开始,找到所有测试模块并返回一个包含它们对象的TestSuite,然后进行加载与模式匹配到唯一的测试文件。discover(dir,pattern,top_level_dir=None)

    <可以存放指定文件夹下所有以特定格式命名的测试脚本中类的所有以test_开头的方法>

test001.py:

from selenium import webdriver
import time
import unittest
from selenium.common.exceptions import NoAlertPresentException
# 继承自unittest.TestCase
class testCase1(unittest.TestCase):
    # 测试固件 (默认运行)
    def setUp(self):   # self为类的实例
        self.driver = webdriver.Chrome()
        self.url = "https://www.baidu.com/"
        self.driver.get(self.url)
        self.driver.maximize_window()
        time.sleep(3)

    # 测试固件
    def tearDown(self):
        self.driver.quit()

    # 以test_开头的方法(默认运行)
    def test_baidu1(self):
        driver = self.driver
        driver.find_element_by_id("kw").send_keys("诗诗")
        driver.find_element_by_id("su").click()
        time.sleep(3)

    def test_baidu2(self):
        driver = self.driver
        driver.find_element_by_link_text("新闻").click()
        time.sleep(3)

    # 普通命名的方法,只有被调用才执行
    def is_alert_exist(self):
        driver = self.driver
        try:
            alert = driver.switch_to.alert
        except NoAlertPresentException as e:
            return False
        return True

    # 入口
    if __name__ == "__main__":
        unittest.main(verbosity=0)

test002.py:

from selenium import webdriver
import time
import unittest
from selenium.common.exceptions import NoAlertPresentException

class testCase2(unittest.TestCase): # 继承自unittest.TestCase
    # 测试固件 (默认运行)
    def setUp(self):   # self为类的实例
        self.driver = webdriver.Chrome()
        self.url = "https://www.baidu.com/"
        self.driver.get(self.url)
        self.driver.maximize_window()
        time.sleep(3)

    # 测试固件
    def tearDown(self):
        self.driver.quit()

    # 以test_开头的方法(默认运行)
    def test_baidu1(self):
        driver = self.driver
        driver.find_element_by_id("kw").send_keys("华为")
        driver.find_element_by_id("su").click()
        time.sleep(5)

    def test_baidu2(self):
        driver = self.driver
        driver.find_element_by_link_text("hao123").click()
        time.sleep(3)

    # 普通命名的方法,只有被调用才执行
    def is_alert_exist(self):
        driver = self.driver
        try:
            alert = driver.switch_to.alert
        except NoAlertPresentException as e:
            return False
        return True

    # 入口
    if __name__ == "__main__":
        unittest.main(verbosity=0)

testsuite.py:

import unittest
from unittest_test import test001, test002

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

    # 1、addTest() 用法
    # 将测试用例加入到测试套件中
    # suite.addTest(test001.testCase1("test_baidu1"))
    # suite.addTest(test001.testCase1("test_baidu2"))
    # suite.addTest(test002.testCase2("test_baidu1"))
    # suite.addTest(test002.testCase2("test_baidu2"))
    # return suite

    # 2、TestLoder用法
    # suite1 = unittest.TestLoader.loadTestsFromTestCase(test001.testCase1)
    # suite2 = unittest.TestLoader.loadTestsFromTestCase(test002.testCase2)
    # suite = unittest.TestSuite([suite1,suite2])
    # return suite

    # 3、discover 用法
    discover = unittest.defaultTestLoader.discover('../unittest_test',pattern='test00*.py',top_level_dir=None)
    print(discover)
    return discover

if __name__ == "__main__":
    suite = createSuite()
    # 执行测试
    runner = unittest.TextTestRunner(verbosity=2)  # 是否显示执行结果详细信息
    runner.run(suite)
2、用例的执行顺序

​ unittest 框架默认加载测试用例的顺序是根据ASCII 码的顺序,数字与字母的顺序为: 0~ 9 ,A~ Z,a~ z 。所以, TestAdd 类会优先于TestBdd 类被发现, test_aaa() 方法会优先于test_ccc() 被执行。对于测试目录与测试文件来说, unittest 框架同样是按照这个规则来加载测试用例。

addTest()方法按照增加顺序来执行。

3、忽略某个测试用例的执行

​ 在测试方法前加@unittest.skip("skipping")

三、unittest断言

自动化的测试中, 对于每个单独的case来说,一个case的执行结果中, 必然会有期望结果与实际结果, 来判断该case是通过还是失败, 在unittest 的库中提供了大量的实用方法来检查预期值与实际值, 来验证case的结果, 一般来说, 检查条件大体分为等价性, 逻辑比较以及其他, 如果给定的断言通过, 测试会继续执行到下一行的代码, 如果断言失败, 对应的case测试会立即停止或者生成错误信息( 一般打印错误信息即可) ,但是不要影响其他的case执行。

unittest 的单元测试库提供了标准的xUnit 断言方法,常用的断言方法如下:

assertEqual(arg1, arg2, msg=None) 验证arg1=arg2,不等则fail;

assertNotEqual(arg1, arg2, msg=None)验证arg1!=arg2,等则fail;

assertTrue(expr, msg=None) 验证expr是true,如果为false,则fail;

assertFalse(expr,msg=None) 验证expr是false,如果为true,则fail。

四、HTML报告生成
import unittest,csv
import os,sys
import time
import HTMLTestRunner

def createSuite():
    discover = unittest.defaultTestLoader.discover('../unittest_test', pattern='test00*.py', top_level_dir=None)
    print(discover)
    return discover

if __name__ == "__main__":
    # 获取当前文件所在的路径
    curpath = sys.path[0]
    print(curpath)
    if not os.path.exists(curpath+"/resultReport"):
        os.mkdir(curpath+"/resultReport")
    # 格式化时间
    now = time.strftime("%Y-%m-%d-%H %M %S", time.localtime(time.time())) # 将当前时间转化为时间戳,time.time() :Linux时间戳
    filename = curpath+"/resultReport/"+now+"-"+"resultReport.html"
    # 往文件里面输出(写)测试结果
    with open(filename, 'wb') as fp:  # wb:以二进制写文件 , with as 可自动调用close关闭文件
    # 定义 HTMLTestRunner 测试报告,stream 定义报告所写入的文件;title 为报告的标题;description 为报告的说明与描述
    runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title=u"测试报告",description=u"测试用例执行的结果",verbosity=2
    suite = createSuite()
    # runner.run()运行测试容器中的用例,并将结果写入的报告中
    runner.run(suite)
五、错误截图
from selenium import webdriver
import time
import unittest
import os
from selenium.common.exceptions import NoAlertPresentException
# 继承自unittest.TestCase
class testCase1(unittest.TestCase):
    # 测试固件 (默认运行)
    def setUp(self):   # self为类的实例
        self.driver = webdriver.Chrome()
        self.url = "https://www.baidu.com/"
        # self.driver.get(self.url)
        self.driver.maximize_window()
        time.sleep(3)

    # 测试固件
    def tearDown(self):
        self.driver.quit()

    def test_baidu(self):
        driver = self.driver
        driver.get(self.url)
        # 判断是否已打开百度页面
        try:
            self.assertEqual(driver.title, "百度_你就知道", msg="打开失败")
        except:
            self.save_error_image(driver, "baidu.png")
        time.sleep(3)

    def save_error_image(self, driver, name):
        if not os.path.exists("./errorImage"):
            os.makedirs("./errorImage")
        now = time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time()))
        self.driver.get_screenshot_as_file('./errorImage/'+now+"-"+name)

    if __name__ == "__main__":
        unittest.main(verbosity=0)
六、数据驱动
  1. ​ 定义:

    • 相同的测试脚本使用不同的测试数据来执行;

    • 测试数据和测试行为完全分离;

    • 是一种测试脚本设计模式。

  2. python 的unittest 没有自带数据驱动功能。所以如果使用unittest,同时又想使用数据驱动,那么就可以使用ddt
    来完成。

  3. ddt的安装:打开cmd输入pip install ddt在线安装.

    pip install ddt

  4. ddt的API:

    • ddt.data:装饰测试方法。参数是一系列的值。
    • ddt.file_data:装饰测试方法。参数是文件名。文件可以是json 或者 yaml类型。
    • ddt.unpack:传递的是复杂的数据结构时使用。比如使用元组或者列表,添加unpack之后,ddt会自动把元组或者列表对应到多个参数上。字典也可以这样处理。
    #test_baidu_data.json	
    [
      "腾讯",
      "阿里巴巴",
      "华为"
    ]
    

    dataDriver_test.py:

    from selenium import webdriver
    import time
    import unittest
    from selenium.common.exceptions import NoAlertPresentException
    from ddt import ddt,file_data,unpack,data
    import os,sys
    
    # 继承自unittest.TestCase
    @ddt
    class testCase1(unittest.TestCase):
        # 测试固件 (默认运行)
        def setUp(self):   # self为类的实例
            self.driver = webdriver.Chrome()
            self.url = "https://www.baidu.com/"
            self.driver.get(self.url)
            self.driver.maximize_window()
            time.sleep(3)
    
        # 测试固件
        def tearDown(self):
            self.driver.quit()
    
        # @data("腾讯","华为","阿里巴巴")
        # @file_data("test_baidu_data.json")
        @data(["Lisa","Lisa_百度搜索"],["Jolin","Jolin_百度搜索"])
        @unpack
        def test_baidu(self,value1,value2):
            driver = self.driver
            driver.find_element_by_id("kw").send_keys(value1)
            driver.find_element_by_id("su").click()
            time.sleep(3)
            print(driver.title)
            self.assertEqual(driver.title,value2,msg="fail")
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值