自动化测试之unittest框架详解

news2024/9/16 22:58:51

1、什么是Unittest框架?

    python自带一种单元测试框架

2、为什么使用UnitTest框架?

    >批量执行用例
    >提供丰富的断言知识
    >可以生成报告

3、核心要素

  1).TestCase(测试用例)
  2).TestSuite(测试套件)
  3).TestRunner(测试执行,执行TestUite测试套件的)
  4).TestLoader(批量执行测试用例-搜索指定文件夹内指定字母开头的模块) 【推荐】
  5) Fixture(固定装置(两个固定的函数,一个初始化时使用,一个结束时使用))

接下来会展开 核心要素来认识unittest框架:

首先介绍下unittest的用例规则:

​ 1、测试文件必须导包:import unittest

​ 2、测试类必须继承 unittest.TestCase

​ 3、测试方法必须以 test_开头

一、TestCase(测试用例)

1、是一个代码文件,在代码文件中来书写真正的用例代码 (里面的print均是模拟测试用例)

  1. # 1、导包

  2. # 2、自定义测试类

  3. # 3、在测试类中书写测试方法 采用print 简单书写测试方法

  4. # 4、执行用例

  5. import unittest

  6. # 2、自定义测试类,需要继承unittest模块中的TestCase类即可

  7. class TestDemo(unittest.TestCase):

  8. # 书写测试方法,测试用例代码,书写要求,测试方法必须test_ 开头

  9. def test_method1(self):

  10. print('测试方法1-1')

  11. def test_method2(self):

  12. print('测试方法1-2')

  13. # 4、执行测试用例

  14. # 4.1 光标放在类后面执行所有的测试用例

  15. # 4.2 光标放在方法后面执行当前的方法测试用例

说明:def 定义的test_ 是测试用例,只有执行 if __name__ == '___mian___' 的时候会执行测试用例,其他普通函数则不执行,通过 self 来调用执行。

二、TestSuite(测试套件)和TestRunner(测试执行)

1、TestSuite(测试套件):用来组装,打包 ,管理多个TestCase(测试用例)文件的

2、TestRunner(测试执行):用来执行 TestSuite(测试套件的)

代码:首先要准备多个测试用例的文件才可以实现TestSuite和TestRunner,以下代码是已经准备了unittest_Demo2和unittest_Demo1两个测试用例文件

  1. # 1、导包

  2. # 2、实例化(创建对象)套件对象

  3. # 3、使用套件对象添加用例方法

  4. # 4、实例化对象运行

  5. # 5、使用运行对象去执行套件对象

  6. import unittest

  7. from unittest_Demo2 import TestDemo

  8. from unittest_Demo1 import Demo

  9. suite = unittest.TestSuite()

  10. # 将⼀个测试类中的所有⽅法进⾏添加

  11. # 套件对象.addTest(unittest.makeSuite(测试类名))

  12. suite.addTest(unittest.makeSuite(TestDemo))

  13. suite.addTest(unittest.makeSuite(Demo))

  14. # 4、实例化运行对象

  15. runner = unittest.TextTestRunner();

  16. # 5、使用运行对象去执行套件对象

  17. # 运⾏对象.run(套件对象)

  18. runner.run(suite)

三、TestLoader(测试加载)

说明:

1. 将符合条件的测试方法添加到测试套件中
2. 搜索指定目录文件下指定字母开头的模块文件下test开始的方法,并将这些方法添加到测试套件中,最后返回测试套件
3. 与Testsuite功能一样,对他功能的补充,用来组装测试用例

一般测试用例是写在Case这个文件夹里面,当测试用例超多的时候就可以考虑 TestLoader

  1. 写法:

  2. 1. suite = unittest.TestLoader().discover("指定搜索的目录文件","指定字母开头模块文件")

  3. 2. suite = unittest.defaultTestLoader.discover("指定搜索的目录文件","指定字母开头模块文件") 【推荐】

  4. 注意:

  5. 如果使用写法1,TestLoader()必须有括号。

 
  1. # 1. 导包

  2. # 2. 实例化测试加载对象并添加用例 ---> 得到的是 suite 对象

  3. # 3. 实例化 运行对象

  4. # 4. 运行对象执行套件对象

  5. import unittest

  6. # 实例化测试加载对象并添加用例 ---> 得到的是 suite 对象

  7. # unittest.defaultTestLoader.discover('用例所在的路径', '用例的代码文件名')

  8. # 测试路径:相对路径

  9. # 测试文件名:可以使用 * 通配符,可以重复使用

  10. suite = unittest.defaultTestLoader.discover('./Case', 'cs*.py')

  11. runner = unittest.TextTestRunner()

  12. runner.run(suite)

  13. TestSuite与TestLoader区别:

  14. 共同点:都是测试套件

  15. 不同点:实现方式不同

  16. TestSuite: 要么添加指定的测试类中所有test开头的方法,要么添加指定测试类中指定某个test开头的方法

  17. TestLoader: 搜索指定目录下指定字母开头的模块文件中以test字母开头的方法并将这些方法添加到测试套件中,最后返回测试套件

四、Fixture(测试夹具)

是一种代码结构,在某些特定情况下,会自动执行。

4.1 方法级别

在每个测试方法(用例代码)执行前后都会自动调用的结构

def setUp(),每个测试方法执行之前都会执行 (初始化)
def tearDown(),每个测试方法执行之后都会执行 (释放)

特性:几个测试函数,执行几次。每个测试函数执行之前都会执行 setUp,执行之后都会执行tearDwon

 
  1. # 初始化

  2. def setUp(self):

  3. # 每个测试方法执行之前执行的函数

  4. pass

  5. # 释放

  6. def tearDown(self):

  7. # 每个测试方法执行之后执行的函数

  8. pass

 
  1. 场景:当你要登录自己的用户名账户的时候,都会输入网址,当你准备不用这个页面了,都会关闭当前页面;

  2. 1、输入网址 (方法级别)

  3. 2、关闭当前页面 (方法级别)

4.2 类级别

在每个测试类中所有方法执行前后 都会自动调用的结构(在整个类中 执行之前执行之后各一次)

def setUpClass() ,类中所有方法之前
def tearDownClass(),类中所有方法之后

特性:测试类运行之前运行一次setUpClass ,类运行之后运行一次tearDownClass

注意:类方法必须使用 @classmethod修饰

 
  1. @classmethod

  2. def setUpClass(cls):

  3. print('-----------1.打开浏览器')

  4. @classmethod

  5. def tearDownClass(cls):

  6. print('------------5、关闭浏览器')

场景:你上网的整个过程都首先需要打开浏览器,关闭浏览器,而他们整个过程都需要执行一次,那么就可以用类级别。

案列模板:结合了类级别和方法级别实现的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GBxQV2uP-1647245316010)(C:/Users/15277/AppData/Roaming/Typora/typora-user-images/image-20220303153824329.png)]

  1. 提示:

  2. 无论使用函数级别还是类级别,最后常用场景为:

  3. 初始化:

  4. 1. 获取浏览器实例化对象

  5. 2. 最大化浏览器

  6. 3. 隐式等待

  7. 结束:

  8. 关闭浏览器驱动对象

五、断言 ☆

1、什么是断言

让程序代替人工自动的判断预期结果和实际结果是否相符

断言的结果:

​ 1)、True,用例通过

​ 2)、False,代码抛出异常,用例不通过

​ 3)、在unittest中使用断言,需要通过 self.断言方法

2、为什么要断言

​ 自动化脚本执行时都是无人值守,需要通过断言来判断自动化脚本的执行是否通过

​ 注:自动化脚本不写断言,相当于没有执行测试一个效果。

3、常用的断言

 
  1. self.assertEqual(ex1, ex2) # 判断ex1 是否和ex2 相等

  2. self.assertIn(ex1, ex2) # ex2是否包含 ex1 注意:所谓的包含不能跳字符

  3. self.assertTrue(ex) # 判断ex是否为True

  4. 重点讲前两个assertEqual 和 assertIn

  5. 方法:

  6. assertEqual:self.assertEqual(预期结果,实际结果) 判断的是预期是否相等实际

  7. assertIn:self.assertIn(预期结果,实际结果) 判断的是预期是否包含实际中

  8. assertIn('admin', 'admin') # 包含

  9. assertIn('admin', 'adminnnnnnnn') # 包含

  10. assertIn('admin', 'aaaaaadmin') # 包含

  11. assertIn('admin', 'aaaaaadminnnnnnn') # 包含

  12. assertIn('admin', 'addddddmin') # 不是包含

 
  1. # Login 函数我已经封装好了,这里直接导包调用就可以了。

  2. import unittest

  3. from login import Login

  4. class TestLogin(unittest.TestCase):

  5. """正确的用户名和密码: admin, 123456, 登录成功"""

  6. def test_success(self):

  7. self.assertEqual('登录成功', Login('admin', '123456'))

  8. def test_username_error(self):

  9. """错误的用户名: root, 123456, 登录失败"""

  10. self.assertEqual('登录失败', Login('root', '123456'))

  11. def test_password_error(self):

  12. """错误的密码: admin, 123123, 登录失败"""

  13. self.assertEqual('登录失败', Login('admin', '123123'))

  14. def test_error(self):

  15. """错误的用户名和错误的密码: aaa, 123123, 登录失败"""

  16. # self.assertEqual('登录失败',Login('登陆失败','123123'))

  17. self.assertIn('失败', Login('登录失败', '123123'))

六、跳过

对于一些未完成的或者不满足测试条件的测试函数和测试类, 不想执行,可以使用跳过

  1. """

  2. 使用方法,装饰器完成

  3. 代码书写在 TestCase 文件

  4. """

  5. # 直接将测试函数标记成跳过

  6. @unittest.skip('跳过条件')

  7. # 根据条件判断测试函数是否跳过 , 判断条件成立, 跳过

  8. @unittest.skipIf(判断条件,'跳过原因')

 
  1. import unittest

  2. version = 20

  3. class TestDemo1(unittest.TestCase):

  4. @unittest.skip('直接跳过')

  5. def test_method1(self):

  6. print('测试用例1-1')

  7. @unittest.skipIf(version > 19, '版本大于19,测试跳过')

  8. def test_method2(self):

  9. print('测试用例1-2')

结果:

七、数据驱动(unittest ddt)☆

ddt:data-driver tests

数据驱动: 是以数据来驱动整个测试用例的执行, 也就是测试数据决定测试结果

数据驱动解决的问题是:

1)、代码和数据分离,避免代码冗余

2)、不写重复的代码逻辑;

在python解释器中需要安装 ddt 这个包才能用:

要检查是否安装上,在cmd当中 输入 pip list命名,有ddt说明安装成功

语法:

1、使用数据驱动,要在class前加上修饰器 @ddt

说明:方法里面使用 print ,为了方便,模拟测试用例,主要是为了学习数据驱动,实际中方法里面写的是测试用例的代码

  1. import unittest

  2. from ddt import ddt, data

  3. @ddt

  4. class TestDemo(unittest.TestCase):

  5. # 单一参数

  6. @data('17611110000', '17611112222')

  7. def test_1(self, phone):

  8. print('测试一电话号码:', phone)

  9. if __name__ == '__main__':

  10. unittest.main()

  11. else:

  12. pass

1)、结合 selenium 使用 ddt

  1. """

  2. unittest + selenium

  3. """

  4. import unittest

  5. from time import sleep

  6. from ddt import ddt, data

  7. from selenium import webdriver

  8. @ddt

  9. class TestBaidu(unittest.TestCase):

  10. def setUp(self) -> None:

  11. self.driver = webdriver.Chrome()

  12. self.driver.get('https://www.sogou.com/')

  13. def tearDown(self) -> None:

  14. sleep(3)

  15. self.driver.quit()

  16. # 单一参数

  17. @data('易烊千玺', '王嘉尔')

  18. def test_01(self, name):

  19. self.driver.find_element_by_id('query').send_keys(name)

  20. self.driver.find_element_by_id('stb').click()

  21. if __name__ == '__main__':

  22. unittest.main()

self:相当于java中的this,当前对象的引用,self.driver定义了driver这个变量。

2、在实际中不可能是单一参数进行传参,将会使用多个参数进行传参:

  1. 注意事项:

  2. 1)、多个数据传参的时候@data里面是要用列表形式

  3. 2)、会用到 @unpack 装饰器 进行拆包,把对应的内容传入对应的参数;

  4. import unittest

  5. from ddt import ddt, data, unpack

  6. @ddt

  7. class TestDemo(unittest.TestCase):

  8. # 多参数数据驱动

  9. @data(['admin', '123456'])

  10. # unpack 是进行拆包,不然会把列表里面的数据全部传到username这个一个参数,我们要实现列表中的两个数据分别传入对应的变量中

  11. @unpack

  12. def test_2(self, username, password):

  13. print('测试二:', username, password)

  14. if __name__ == '__main__':

  15. unittest.main()

  16. else:

  17. pass

但是以上步骤都是数据在代码当中的,假如要测试n个手机号这样的数据,全部写在 @data 装饰器里面就很麻烦,这就引出了数据驱动里面的代码和数据的分离。

3、将数据放入一个文本文件中,从文件读取数据, 如JSON、 excel、 xml、 txt等格式文件 ,这里演示的是json文件类型.

json文件处理, 这个链接介绍了json文件和Python文件基本操作

(1)在json文件驱动

  1. [

  2. {

  3. "username": "admin",

  4. "password": "123456"

  5. },

  6. {

  7. "username": "normal",

  8. "password": "45678"

  9. }

  10. ]

(2)在测试代码中读取json文件

  1. import json

  2. import unittest

  3. from ddt import ddt, data, unpack

  4. # 用json多个参数读取

  5. def reads_phone():

  6. with open('user.json', encoding='utf-8') as f:

  7. result = json.load(f) # 列表

  8. return result

  9. @ddt

  10. class TestDemo(unittest.TestCase):

  11. # 多参数数据驱动

  12. @data(*reads_phone())

  13. # unpack 是进行拆包,不然会把列表里面的数据全部传到username这个一个参数,我们要实现列表中的两个数据分别传入对应的变量中

  14. @unpack

  15. def test_2(self, username, password):

  16. print('测试二:', username, password)

  17. if __name__ == '__main__':

  18. unittest.main()

  19. else:

  20. pass

  1. 注意事项:

  2. 1、with open里面默认是 ”r“

  3. 2、@data 里面的 * 含义是实现每个json对象单个传入方法执行,不然会吧json文件里面所用数据全部传入

  4. > * 是元祖;

  5. > ** 是字典;

  6. 3、参数不能传错,要对应

执行结果:

(3)txt文件驱动
一行表示一组:

  1. admin,123456

  2. normal,456789

  3. import unittest

  4. def read():

  5. lis = []

  6. with open('readtext.txt', 'r', encoding='utf-8') as f:

  7. for line in f.readlines():

  8. # lis.append(line) # ['admin,123456\n', 'normal,456789\n']

  9. # lis.append(line.strip('\n')) ['admin,123456', 'normal,456789'] 两个字符串

  10. lis.append(line.strip('\n').split(',')) # [['admin', '123456'], ['normal', '456789']]

  11. return lis

  12. class TestDome(unittest.TestCase):

  13. def test_01(self):

  14. li = read()

  15. print(li)

  16. if __name__ == '__main__':

  17. unittest.main()

  1. """

  2. split():一个字符串里面用某个字符分割,返回列表

  3. strip():去掉两边的字符或者字符串,默认删除空白符(包括'\n', '\r', '\t', ' ')

  4. """

运行

运行

(4)csv 文件驱动

  1. 供应商名称,联系人,移动电话

  2. 英业达,张三,13261231234

  3. 阿里巴巴,李四,13261231231

  4. 日立公司,王五,13261231233

写法一:

  1. """

  2. 编写 csvv.py脚本读取csv中的测试数据

  3. """

  4. import csv

  5. class ReadCsv():

  6. def read_csv(self):

  7. lis = []

  8. # 用csv的API的reader方法!!!!

  9. data = csv.reader(open('testdata.csv', 'r')) #!!!!

  10. next(data, None)

  11. for line in data:

  12. lis.append(line)

  13. # lis.append(line[0]) # 二维数组可以省略行,列不可以省略

  14. # lis.append(line[1])

  15. return lis

  16. # 实例化类

  17. readCsv = ReadCsv()

  18. # 打印类中的方法

  19. print(readCsv.read_csv())

写法二: 推荐

  1. def csvTest():

  2. li = []

  3. with open('user.csv', 'r', encoding='utf-8') as f:

  4. filename = csv.reader(f)

  5. next(filename, None)

  6. for r in filename:

  7. li.append(r)

  8. return li

(5)yaml文件驱动

  1. -

  2. username: admin9

  3. password: 123456

  4. -

  5. username: normal

  6. password: 789456

对应的json文件

  1. [

  2. {

  3. "username": "admin9",

  4. "password": 123456

  5. },

  6. {

  7. "username": "normal",

  8. "password": 7894

  9. }

  10. ]

写法:

  1. """

  2. 使用yaml数据驱动

  3. """

  4. import unittest

  5. from time import sleep

  6. from selenium import webdriver

  7. from ddt import ddt, data, unpack, file_data

  8. @ddt

  9. class YamlTest(unittest.TestCase):

  10. def setUp(self) -> None:

  11. self.driver = webdriver.Chrome()

  12. self.driver.get('file:///D:/%E6%A1%8C%E9%9D%A2/page/%E6%B3%A8%E5%86%8CA.html')

  13. self.driver.maximize_window()

  14. def tearDown(self) -> None:

  15. driver = self.driver

  16. sleep(3)

  17. driver.quit()

  18. # file_data 传入多个参数的时候,@unpack 的解包不起作用

  19. @unittest.skip

  20. @file_data('../user.yaml')

  21. @unpack

  22. def test_yaml01(self, username, password):

  23. driver = self.driver

  24. driver.find_element_by_id('userA').send_keys(username)

  25. driver.find_element_by_id('passwordA').send_keys(password)

  26. # 注意:传的参数名称要与yaml文件对应

  27. # 在yaml数据中文件中采用对象(键值对)的方式来定义数据内容

  28. @file_data('../user1.yaml')

  29. def test_yaml02(self, username, password):

  30. driver = self.driver

  31. driver.find_element_by_id('userA').send_keys(username)

  32. driver.find_element_by_id('passwordA').send_keys(password)

  33. if __name__ == '__main__':

  34. unittest.main()

注意:file_date 装饰器,可以直接读取yaml和json文件

(6)Excel文件驱动
建立excel表的时候需要退出pychram在根目录下创建excel表保存,否则会报错

  1. def read_excel():

  2. xlsx = openpyxl.load_workbook("../excel.xlsx")

  3. sheet1 = xlsx['Sheet1']

  4. print(sheet1.max_row) # 行

  5. print(sheet1.max_column) # 列

  6. print('=======================================================')

  7. allList = []

  8. for row in range(2, sheet1.max_row + 1):

  9. rowlist = []

  10. for column in range(1, sheet1.max_column + 1):

  11. rowlist.append(sheet1.cell(row, column).value)

  12. allList.append(rowlist)

  13. return allList

用excel登录csdn操作

  1. """

  2. 测试excel数据驱动

  3. """

  4. import unittest

  5. from time import sleep

  6. import openpyxl as openpyxl

  7. from ddt import ddt, data, unpack

  8. from selenium import webdriver

  9. # 读取excel表中的数据,使用xlrd,openpyxl

  10. def read_excel():

  11. xlsx = openpyxl.load_workbook("../excel.xlsx")

  12. sheet1 = xlsx['Sheet1']

  13. print(sheet1.max_row) # 行

  14. print(sheet1.max_column) # 列

  15. print('=======================================================')

  16. allList = []

  17. for row in range(2, sheet1.max_row + 1):

  18. rowlist = []

  19. for column in range(1, sheet1.max_column + 1):

  20. rowlist.append(sheet1.cell(row, column).value)

  21. allList.append(rowlist)

  22. return allList

  23. @ddt

  24. class ExcelText(unittest.TestCase):

  25. def setUp(self) -> None:

  26. self.driver = webdriver.Chrome()

  27. self.driver.get('https://passport.csdn.net/login?code=applets')

  28. self.driver.maximize_window()

  29. def tearDown(self) -> None:

  30. driver = self.driver

  31. sleep(3)

  32. driver.quit()

  33. @data(*read_excel())

  34. @unpack

  35. def test_excel01(self, flag, username, password):

  36. print(flag, username, password)

  37. driver = self.driver

  38. sleep(2)

  39. driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div[2]/div[1]/div/div[1]/span[4]').click()

  40. driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div[2]/div[1]/div/div[2]/div/div[1]/div/input').send_keys(username)

  41. driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div[2]/div[1]/div/div[2]/div/div[2]/div/input').send_keys(password)

  42. driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div[2]/div[1]/div/div[2]/div/div[4]/button').click()

  43. if __name__ == '__main__':

  44. unittest.main()

八、截图操作

用例不可能每一次运行都成功,肯定运行时候有不成功的时候。如果可以捕捉到错误,并且把错误截图保存,这将
是一个非常棒的功能,也会给我们错误定位带来方便

截图方法:driver.get_screenshot_as_file

  1. """

  2. 捕捉异常截图测试

  3. """

  4. import os.path

  5. import time

  6. import unittest

  7. from time import sleep

  8. from selenium import webdriver

  9. class ScreeshotTest(unittest.TestCase):

  10. def setUp(self) -> None:

  11. self.driver = webdriver.Chrome()

  12. self.driver.get('https://www.sogou.com/')

  13. self.driver.maximize_window()

  14. def tearDown(self) -> None:

  15. sleep(3)

  16. driver = self.driver

  17. driver.quit()

  18. def test_01(self):

  19. driver = self.driver

  20. driver.find_element_by_id('query').send_keys("易烊千玺")

  21. driver.find_element_by_id('stb').click()

  22. sleep(3)

  23. print(driver.title)

  24. try:

  25. self.assertEqual(driver.title, u"搜狗一下你就知道", msg="不相等")

  26. except:

  27. self.saveScreenShot(driver, "shot.png")

  28. sleep(5)

  29. def saveScreenShot(self, driver, filename):

  30. if not os.path.exists("./imge"):

  31. os.makedirs("./imge")

  32. # 格式十分重要,小写大写敏感 %Y%m%d-%H%M%S

  33. now = time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time()))

  34. driver.get_screenshot_as_file("./imge/" + now + "-" + filename)

  35. sleep(3)

  36. if __name__ == '__main__':

  37. unittest.main()

九、测试报告

有两种测试报告:

1、自带的测试报告

2、生成第三方测试报告

9.1 自带测试报告

只有单独运行 TestCase 的代码,才会生成测试报告

 

 

9.2 生成第三方测试报告

这里需要第三方的测试运行类模块,然后放在代码的目录中

就像这两个模块一样放进代码目录中

  1. 步骤:

  2. 1. 获取第三方的 测试运行类模块 , 将其放在代码的目录中

  3. 2. 导包 unittest

  4. 3. 使用 套件对象, 加载对象 去添加用例方法

  5. 4. 实例化 第三方的运行对象 并运行 套件对象

  6. HTMLTestRunner()

写法一:

 
  1. import unittest

  2. from HTMLTestRunner import HTMLTestRunner

  3. suite = unittest.defaultTestLoader.discover('.', 'Uni*.py')

  4. file = 'report1.html'

  5. with open(file, 'wb') as f:

  6. runner = HTMLTestRunner(f, 2, '测试报告', 'python3.10') # 运行对象

  7. # 运行对象执行套件, 要写在 with 的缩进中

  8. runner.run(suite)

写法二:

  1. """

  2. 生成测试报告

  3. """

  4. import os.path

  5. import sys

  6. import time

  7. import unittest

  8. from time import sleep

  9. from HTMLTestRunner import HTMLTestRunner

  10. def createsuite():

  11. discovers = unittest.defaultTestLoader.discover("./cases", pattern="cs*.py")

  12. print(discovers)

  13. return discovers

  14. if __name__ == '__main__':

  15. # 当前路径

  16. # sys.path 是一个路径的集合

  17. curpath = sys.path[0]

  18. print(sys.path)

  19. print(sys.path[0])

  20. # 当前路径文件resultreport不存在时,就创建一个

  21. if not os.path.exists(curpath+'/resultreport'):

  22. os.makedirs(curpath+'/resultreport')

  23. # 2、解决重名问题

  24. now = time.strftime("%Y-%m-%d-%H %M %S", time.localtime(time.time()))

  25. print(time.time())

  26. print(time.localtime(time.time()))

  27. # 文件名是 路径 加上 文件的名称

  28. filename = curpath+'/resultreport/'+now+'resultreport.html'

  29. # 打开文件html,是用wb以写的方式打开

  30. with open(filename, 'wb') as f:

  31. runner = HTMLTestRunner(f, 2, u"测试报告", u"测试用例情况")

  32. suite = createsuite()

  33. runner.run(suite)

这里面的当前路径也可以用 ./来表示!!!

  1. """

  2. 生成测试报告

  3. """

  4. import os.path

  5. import sys

  6. import time

  7. import unittest

  8. from time import sleep

  9. from HTMLTestRunner import HTMLTestRunner

  10. def createsuite():

  11. discovers = unittest.defaultTestLoader.discover("./cases", pattern="cs*.py")

  12. print(discovers)

  13. return discovers

  14. if __name__ == '__main__':

  15. # 当前路径文件resultreport不存在时,就创建一个

  16. if not os.path.exists('./resultreport'):

  17. os.makedirs('./resultreport')

  18. # 2、解决重名问题

  19. # 格式十分重要 %Y-%m-%d-%H %M %S

  20. now = time.strftime("%Y-%m-%d-%H %M %S", time.localtime(time.time()))

  21. print(time.time())

  22. print(time.localtime(time.time()))

  23. # 文件名是 路径 加上 文件的名称

  24. filename = './resultreport/'+now+'resultreport.html'

  25. # 打开文件html,是用wb以写的方式打开

  26. with open(filename, 'wb') as f:

  27. runner = HTMLTestRunner(f, 2, u"测试报告", u"测试用例情况")

  28. suite = createsuite()

  29. runner.run(suite)

注意:

实例化 第三方的运行对象,HTMLTestRunner()的初始化有多种可以自定义设置

  1. HTMLTestRunner()

  2. 1、stream=sys.stdout, 必填,测试报告的文件对象(open ), 注意点,要使用 wb 打开

  3. 2、verbosity=1, 可选, 报告的详细程度,默认 1 简略, 2 详细

  4. 3、title=None, 可选, 测试报告的标题

  5. 4、description=None 可选, 描述信息, Python 的版本, pycharm 版本

最后生成结果:

​unittest框架就本上就是这些知识了,里面记得东西很多,多敲代码,形成记忆,自动化测试后面还剩下selenium,selenium完了过后基本上自动化的内容差不多就结束了。

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1912023.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

比赛获奖的武林秘籍:05 电子计算机类比赛国奖队伍技术如何分工和学习内容

比赛获奖的武林秘籍:05 电子计算机类比赛国奖队伍技术如何分工和学习内容 摘要 本文主要介绍了在电子计算机类比赛中技术层面上的团队分工和需要学习的内容,分为了嵌入式硬件、嵌入式软件、视觉图像处理、机械、上位机软件开发和数据分析等六个方向&am…

ORA-12537: TNS:连接关闭/Io 异常: Got minus one from a read call

在另外一个数据库建立dblink的时候,发现执行命令报错: 被连接的数据库我也上去过,用工具尝试登陆也报错: IO Error: Got minus one from a read call, connect lapse 1 ms., Authentication lapse 0 ms. Got minus one from a …

PTA - 编写函数计算圆面积

题目描述: 1.要求编写函数getCircleArea(r)计算给定半径r的圆面积,函数返回圆的面积。 2.要求编写函数get_rList(n) 输入n个值放入列表并将列表返回 函数接口定义: getCircleArea(r); get_rList(n); 传入的参数r表示圆的半径&#xff0c…

新闻资讯整合平台:一站式满足企业信息需求

摘要: 面对信息爆炸的时代,企业如何在海量数据中快速获取有价值资讯,成为提升竞争力的关键。本文将探讨如何通过一站式新闻资讯整合平台,实现企业信息需求的全面满足,提升决策效率,同时介绍实用工具推荐&a…

如何构建数据驱动的企业?爬虫管理平台是关键桥梁吗?

一、数据驱动时代:为何选择爬虫管理平台? 在信息爆炸的今天,数据驱动已成为企业发展的核心战略之一。爬虫管理平台,作为数据采集的第一站,它的重要性不言而喻。这类平台通过自动化手段,从互联网的各个角落…

AI Earth——1990-2022年全国月度气象数据检索应用app

应用结果 代码 #导入安装包 import os import json import datetime import streamlit as st import streamlit.components.v1 as components import traceback from PIL import Imageimport aie#读取当前目录的内容 current_work_dir = os.path.dirname(__file__) #添加地图…

PolarisMesh源码系列——服务端启动流程

前话 PolarisMesh(北极星)是腾讯开源的服务治理平台,致力于解决分布式和微服务架构中的服务管理、流量管理、配置管理、故障容错和可观测性问题,针对不同的技术栈和环境提供服务治理的标准方案和最佳实践。 PolarisMesh 官网&am…

开发个人Go-ChatGPT–6 OpenUI

开发个人Go-ChatGPT–6 OpenUI Open-webui Open WebUI 是一种可扩展、功能丰富且用户友好的自托管 WebUI,旨在完全离线运行。它支持各种 LLM 运行器,包括 Ollama 和 OpenAI 兼容的 API。 功能 由于总所周知的原由,OpenAI 的接口需要密钥才…

网络安全——防御实验

防御实验一 拓扑结构展示: 一、 根据题目,先为办公区做安全策略主要策略有以下几点: 1、书写名称和描述,名称和描述要明确,让除本人以外的人也能理解 2、确定源地址为办公区,目标地址为DMZ区 3、确定时间…

QT程序异常结束解决方法

在用QT开发第三方SDK的时候,刚开始是运行正常的,但是重装系统之后再次运行程序总是出现:程序异常结束。 以下方法尝试无效,但不失为一种排查方法: 重新安装QT;检查Qt Creator配置,编译器位数和…

java LogUtil输出日志打日志的class文件内具体方法和行号

最近琢磨怎么把日志打的更清晰,方便查找问题,又不需要在每个class内都创建Logger对象,还带上不同的颜色做区分,简直不要太爽。利用堆栈的方向顺序拿到日志的class问题。看效果,直接上代码。 1、demo test 2、输出效果…

什么是O2O?线上线下怎么完美结合?

现如今互联网技术飞速发展,智能手机普及。O2O(Online To Offline)模式已经成为一种新的商业模式,人们的生活和消费习惯也逐渐被改变。经常听到企业提到“O2O”,它究竟是什么呢?对企业有着什么魅力呢&#x…

随笔(一)

1.即时通信软件原理(发展) 即时通信软件实现原理_即时通讯原理-CSDN博客 笔记: 2.泛洪算法: 算法介绍 | 泛洪算法(Flood fill Algorithm)-CSDN博客 漫水填充算法实现最常见有四邻域像素填充法&#xf…

idea创建dynamic web project

由于网课老师用的是eclipse,所以又得自己找教程了…… 解决方案: https://blog.csdn.net/Awt_FuDongLai/article/details/115523552

【状态估计】非线性非高斯系统的状态估计——离散时间的批量估计

上一篇文章介绍了离散时间的递归估计,本文着重介绍离散时间的批量估计。 上一篇位置:【状态估计】非线性非高斯系统的状态估计——离散时间的递归估计。 离散时间的批量估计问题 最大后验估计 目标函数 利用高斯-牛顿法来解决估计问题的非线性版本&a…

绝区伍--2024年AI发展路线图

2024 年将是人工智能具有里程碑意义的一年。随着新模式、融资轮次和进步以惊人的速度出现,很难跟上人工智能世界发生的一切。让我们深入了解 2024 年可能定义人工智能的关键事件、产品发布、研究突破和趋势。 2024 年第一季度 2024 年第一季度将推出一些主要车型并…

添加点击跳转页面,优化登录和注册页路由

一、给注销按钮添加点击跳转至登录页 1、在路由中添加登录页路由 2、自定义登录页面 3、在app.vue页面找到下拉框组件,添加点击事件 4、使用vue-router中的useRoute和useRouter 点击后可以跳转,但是还存在问题,路径这里如果我们需要更改登录…

springboot基于Java的超市进销存系统+ LW+ PPT+源码+讲解

第三章系统分析与设计 3.1 可行性分析 一个完整的系统,可行性分析是必须要有的,因为他关系到系统生存问题,对开发的意义进行分析,能否通过本网站来补充线下超市进销存管理模式中的缺限,去解决其中的不足等&#xff0c…

Qt入门(二):Qt的基本组件

目录 Designer程序面板 1、布局Layout 打破布局 贴合窗口 2、QWidget的属性 3、Qlabel标签 显示图片 4、QAbstractButton 按钮类 按钮组 5、QLineEdit 单行文本输入框 6、ComboBox 组合框 7、若干与数字相关的组件 Designer程序面板 Qt包含了一个Designer程序 &…

02day-C++学习(const 指针与引用的关系 inline nullptr)

02day-C学习 1. 使用const注意事项 注意事项 • 可以引⽤⼀个const对象,但是必须⽤const引⽤。const引⽤也可以引⽤普通对象,因为对象的访 问权限在引⽤过程中可以缩⼩,但是不能放⼤。 • 不需要注意的是类似 int& rb a3; double d 1…