当前位置: 首页 > news >正文

自动化测试:电商管理系统元素定位练习​

本次专题我们来说一下 Python中Unittest 框架的使用及如何通过HTMLTestRunner实现自动化测试报告的自动生成。案例中的代码我们仍旧使用课堂学习中部署的“电商管理系统”来实现。本次练习包括以下几个操作:

l 测试用例整体结构设计

l 测试用例的实现

l 测试套的组织及测试报告的生成

1. 测试用例整体结构设计

Unittest原名为PyUnit,是由java的JUnit衍生而来,用于编写和运行可重复的测试。基于断言机制来判断函数或方法的实际输出结果和期望输出结果是否一致,测试用例提供参数来执行函数或方法,获取它们的执行结果,然后使用断言方法来判断该函数或方法的输出结果与期望输出结果是否一致,如果一致则说明测试通过;如果不一致则说明测试不通过。

Unittest 要求单元测试类必须继承 TestCase,该类中的测试方法应以test开头,没有参数和返回值。另外可以通过在单元测试中增加两个特殊函数setUp()和tearDown()函数,用于实现在每调用一个测试方法的前后分别执行指定的动作,其中setUp是在测试函数调用前执行,tearDown是在之后执行。

我们首先为登录功能编写一个测试用例,代码结构如下,一共演示包括三个测试方法:

在这里插入图片描述

2. 测试用例的实现

接下来我们完成测试用例内容的实现。按照上面的结构,一共实现两个测试用例,一个登录的测试用例,一个增加商品类型的测试用例。

登录测试用例。这里将系统登录页面的打开和关闭功能分别封装进setUp和tearDown函数内部,这样后续每个方法执行的前后会自动打开登录页面并在测试执行之后关闭登录页面。

代码实现如下:

import unittest
from time import sleep
from selenium import webdriver# 登录测试用例
class LoginTest(unittest.TestCase):# 每执行一个测试方法前,先打开登录页面def setUp(self):self.driver = webdriver.Firefox()self.driver.implicitly_wait(10)self.driver.get('http://39.96.181.61/qftest-ds/index.php?m=backend&c=main&a=index')# 每执行一个测试方法后,关闭浏览器def tearDown(self):self.driver.quit()# 测试方法1:无效用户名登录测试def test_01_invalid_username(self):self.driver.find_element_by_id("username").send_keys('abcdefg')self.driver.find_element_by_id("password").send_keys('qftestxxxxx')self.driver.find_element_by_link_text('登 陆').click()sleep(2)# 断言:如果登录失败,应该显示提示信息,包含文字:"错误的用户名或密码"self.assertIn('错误的用户名或密码', self.driver.page_source)# 测试方法2:无效密码登录测试def test_02_invalid_password(self):self.driver.find_element_by_id("username").send_keys('admin')self.driver.find_element_by_id("password").send_keys('123456')self.driver.find_element_by_link_text('登 陆').click()sleep(2)# 断言:如果登录失败,应该显示提示信息,包含文字:"错误的用户名或密码"self.assertIn('错误的用户名或密码', self.driver.page_source)# 测试方法3:有效用户名和密码登录测试def test_03_valid(self):self.driver.find_element_by_id("username").send_keys('admin')self.driver.find_element_by_id("password").send_keys('qftestxxxxxx')self.driver.find_element_by_link_text('登 陆').click()sleep(2)# 断言:如果登录成功,应该进入系统桌面,包含文字:"常用菜单"self.assertIn('常用菜单', self.driver.page_source)if __name__ == "__main__":unittest.main()增加商品类型测试用例。这里将系统登录和退出及关闭浏览器功能分别封装进setUp和tearDown函数内部,这样后续每个方法执行的前后会自动完成登录并在测试执行之后退出和关闭登录页面。
代码实现如下:
import random
import unittest
from time import sleep
from selenium import webdriver
from selenium.webdriver.support.select import Select# 增加商品分类测试用例
class AddTypeTest(unittest.TestCase):def setUp(self):self.driver = webdriver.Firefox()self.driver.implicitly_wait(10)self.driver.get('http://39.96.181.61/qftest-ds/index.php?m=backend&c=main&a=index')self.driver.find_element_by_id("username").send_keys('admin')self.driver.find_element_by_id("password").send_keys('qftestxxxxxxx')self.driver.find_element_by_link_text('登 陆').click()sleep(3)def tearDown(self):self.driver.switch_to.default_content()self.driver.find_element_by_link_text("退出登录").click()sleep(2)self.driver.quit()# 测试方法1:是否可要正确打开商品分类页面def test_01_open_type(self):sleep(5)# 依次点击目录:商品管理 - 商品分类self.driver.find_element_by_xpath('/html/body/div[5]/div[1]/div[2]/h3/a').click()self.driver.find_element_by_partial_link_text('商品分类').click()sleep(5)# 切换到内部 iframeself.driver.switch_to.frame('main')# 断言:如果打开商品分类页面成功,应该包含显示文字:"分类名称"self.assertIn('分类名称', self.driver.page_source)# 测试方法2:是否可要新增商品分类,并且添加成功def test_02_add_type(self):sleep(5)# 依次点击目录:商品管理 - 商品分类self.driver.find_element_by_xpath('/html/body/div[5]/div[1]/div[2]/h3/a').click()self.driver.find_element_by_partial_link_text('商品分类').click()sleep(5)self.driver.switch_to.frame('main')# 点击“新增分类”按钮self.driver.find_element_by_xpath('/html/body/div/div[2]/div[1]/a[1]/font').click()sleep(1)# 输入分类名称self.driver.find_element_by_id('cate_name').send_keys('奥里给')sleep(1)# 从下拉列表中随机选择一个上级分类father_type = self.driver.find_element_by_id('parent_id')father_type_opts = Select(father_type).optionsrom = random.randint(0, len(father_type_opts) - 1)Select(father_type).select_by_index(rom)sleep(1)# 点击“保存并提交”按钮self.driver.find_element_by_css_selector('html body div.content form div.box div.submitbtn button.ubtn.btn').click()sleep(5)# 断言:新增的分类名称,应该显示在返回的分类表格页面中self.assertIn('奥里给', self.driver.page_source)if __name__ == "__main__":unittest.main()

3. 测试套的组织及测试报告的生成

对于测试用例的执行,我们使用unittest下面的测试套件类TestSuite,从它的类定义来看,可以理解为多个独立的测试用例(test case)可以构成一个测试套件。

想让测试用例按顺序执行,要用到TestSuite类的addTest方法。调用addTest方法后,先添加的先执行,后添加的后执行。但是这里提请大家注意一下,在PyCharm中,addTest方法并没有起到作用,原因是在PyCharm中,引入了unittest模块,会默认按照unittest模式执行,此时需要将unittest模式转换成普通模式。

我们在做自动化测试的时候,希望能生一张漂亮的测试报告来展示用例执行的结果,这里我们使用HTMLTestRunner来实现。HTMLTestRunner 是 Python 标准库的 unittest 模块的一个扩展。它生成易于使用的 HTML 测试报告。

代码实现如下:

import unittest
from HTMLTestRunner import HTMLTestRunner
from F01_login_test import LoginTest
from F02_add_type_test import AddTypeTest# 定义测试套(包含要运行的测试用例及方法)
def test_suite():suite = unittest.TestSuite()# 添加第一个测试用例及所属测试方法suite.addTest(LoginTest('test_01_invalid_username'))suite.addTest(LoginTest('test_02_invalid_password'))suite.addTest(LoginTest('test_03_valid'))# 添加第二个测试用例及所属方法suite.addTest(AddTypeTest('test_01_open_type'))suite.addTest(AddTypeTest('test_02_add_type'))return suiteif __name__ == '__main__':# 设置测试报告输出文件with open('./test_report.html', 'wb') as f:runner = HTMLTestRunner(stream=f,title="自动化测试报告",description="电商系统自动化测试报告")# 运行测试套runner.run(test_suite())

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你! 

相关文章:

  • pubg开启之路
  • 防火墙 (iptables)------------------------SNAT与DNAT
  • ADC--模拟量转换成数字量
  • Compose 自定义 - 数据转UI的三阶段(组合、布局、绘制)
  • Mongodb 文本检索
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • html从零开始8:css3新特性、动画、媒体查询、雪碧图、字体图标【搬代码】
  • 【C语言】指针练习篇(下),深入理解指针---指针练习题【图文讲解,详细解答】
  • Python循环语句——for循环的嵌套使用
  • Java学习第十六节之创建对象内存分析和小结类与对象
  • Java实现停车场收费系统 JAVA+Vue+SpringBoot+MySQL
  • Godot 游戏引擎个人评价和2024年规划(无代码)
  • QtApplets-线程池
  • MinGW/MSYS/GCC/GNU/MSVC/Clang/LLVM都是什么
  • 防火墙HA详解
  • 【个人向】《HTTP图解》阅后小结
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • 03Go 类型总结
  • 11111111
  • EventListener原理
  • iOS 颜色设置看我就够了
  • JavaScript-Array类型
  • java中具有继承关系的类及其对象初始化顺序
  • js如何打印object对象
  • LeetCode29.两数相除 JavaScript
  • Python socket服务器端、客户端传送信息
  • Yii源码解读-服务定位器(Service Locator)
  • 计算机在识别图像时“看到”了什么?
  • 如何进阶一名有竞争力的程序员?
  • 为视图添加丝滑的水波纹
  • 硬币翻转问题,区间操作
  • 正则表达式
  • Android开发者必备:推荐一款助力开发的开源APP
  • MPAndroidChart 教程:Y轴 YAxis
  • #define,static,const,三种常量的区别
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (LeetCode) T14. Longest Common Prefix
  • (zhuan) 一些RL的文献(及笔记)
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (二)斐波那契Fabonacci函数
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (转载)利用webkit抓取动态网页和链接
  • **CI中自动类加载的用法总结
  • *1 计算机基础和操作系统基础及几大协议
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .NET CF命令行调试器MDbg入门(一)
  • .NET6 开发一个检查某些状态持续多长时间的类
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】
  • /bin/rm: 参数列表过长"的解决办法