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

news2024/11/23 15:48:49

本次专题我们来说一下 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)
 # 切换到内部 iframe
 self.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).options
        rom = 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 suite


if __name__ == '__main__':
    # 设置测试报告输出文件
    with open('./test_report.html', 'wb') as f:
        runner = HTMLTestRunner(stream=f,
                                title="自动化测试报告",
                                description="电商系统自动化测试报告")
        # 运行测试套
        runner.run(test_suite())

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

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

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

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

相关文章

C++类和对象-多态->多态的基本语法、多态的原理剖析、纯虚函数和抽象类、虚析构和纯虚析构

#include<iostream> using namespace std; //多态 //动物类 class Animal { public: //Speak函数就是虚函数 //函数前面加上virtual关键字&#xff0c;变成虚函数&#xff0c;那么编译器在编译的时候就不能确定函数调用了。 virtual void speak() { …

建造者模式-Builder Pattern

原文地址:https://jaune162.blog/design-pattern/builder-pattern/ 引言 现在一般大型的业务系统中的消息通知的形式都会有多种,比如短信、站内信、钉钉通知、邮箱等形式。虽然信息内容相同,但是展现形式缺不同。如短信使用的是纯文本的形式,钉钉使用的一般是Markdown的形…

MATLAB通信系统仿真设计——基于BPSK的直接序列扩频通信系统仿真

一.实验原理 直接序列扩频&#xff0c;就是直接用高码率的扩频码序列在发端去扩展信号的频谱&#xff0c;在收端用相同的扩频码去解扩&#xff0c;把展宽的扩频信号还原成原始的基带信号。 在发端输入的信息与扩频码发生器产生的伪随机码序列&#xff08;这里使用的是m序列&am…

【C语言相关问题】C语言中关于大小写字母转换的问题

大家好&#xff0c;这里是争做图书馆扫地僧的小白。非常感谢各位的支持&#xff0c;也期待着您的关注。 目前博主有着C语言、C、linux以及数据结构的专栏&#xff0c;内容正在逐步的更新。 希望对各位朋友有所帮助同时也期望可以得到各位的支持&#xff0c;有任何问题欢迎私信与…

【解决】阿里云香港服务器怎么样?cn2性能测试

阿里云香港服务器中国香港数据中心网络线路类型BGP多线精品&#xff0c;中国电信CN2高速网络高质量、大规格BGP带宽&#xff0c;运营商精品公网直连中国内地&#xff0c;时延更低&#xff0c;优化海外回中国内地流量的公网线路&#xff0c;可以提高国际业务访问质量。阿里云服务…

会声会影2024新功能及剪辑视频步骤教程

会声会影2024的新功能主要包括&#xff1a; 全新的标题动态与特效&#xff1a;用户可以为文字标题指定进入、中场和退出的不同动态效果&#xff0c;比如闪现进入、中场弹跳和淡出退出等&#xff0c;让文字标题更具动感。此外&#xff0c;还新增了多个标题特效&#xff0c;包括…

开源数据可视化应用程序JSON Crack

什么是 JSON Crack &#xff1f; JSON Crack 是一款免费的开源数据可视化应用程序&#xff0c;能够将 JSON、YAML、XML、CSV 等数据格式可视化为交互式图表。凭借其直观且用户友好的界面&#xff0c;JSON Crack 可以轻松探索、分析和理解即使是最复杂的数据结构。无论您是从事大…

OpenCV 4基础篇| OpenCV简介

目录 1. 什么是OpenCV2. OpenCV的发展历程3. 为什么用OpenCV4. OpenCV应用领域5. OpenCV的功能模块5.1 基本模块5.2 扩展模块5.3 常用函数目录 1. 什么是OpenCV OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习软件库。它…

CES 2024:NVIDIA 通过新的笔记本电脑、GPU 和工具提供生成式 AI

在 CES 2024 上&#xff0c;NVIDIA 推出了一系列硬件和软件&#xff0c;旨在释放 Windows 11 PC 上生成式 AI 的全部潜力。 在 PC 上本地运行生成式 AI 对于隐私、延迟和成本敏感型应用程序至关重要。在 CES 上&#xff0c;NVIDIA 将在整个技术堆栈中带来新的创新&#xff0c;…

Code Composer Studio (CCS) - Current and Local Revision

Code Composer Studio [CCS] - Current and Local Revision References 鼠标放在文件内的任意位置&#xff0c;鼠标右键 -> Compare With -> Local History -> Revision Time. References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

半导体物理基础-笔记

源内容参考&#xff1a;https://www.bilibili.com/video/BV11U4y1k7zn/?spm_id_from333.337.search-card.all.click&vd_source61654d4a6e8d7941436149dd99026962 半导体物理要解决的四个问题 载流子在哪里&#xff1b;如何获得足够多的载流子&#xff1b;载流子如何运动…

浅析DPDK驱动管理:vhost

文章目录 概述DPDK vhost工作机制DPDK vhost工作模式 DPDK vhost管理结构DPDK vhost接口注册vhost驱动&#xff1a;rte_vhost_driver_register启动vhost&#xff1a;rte_vhost_driver_startvhost消息处理 相关参考 概述 DPDK提供了一套vhost库&#xff0c;用于加速virtio后端&…

EXTI外部中断

&#xff1f; 难点&#xff1a;中断向量表、看门狗、NVIC的优先级位&#xff1f;EXTI框图&#xff1f; ------------------------ 中断系统 中断&#xff1a;在主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;--->例如&#xff1a;…

Unity设备分级策略

Unity设备分级策略 前言 之前自己做的设备分级策略&#xff0c;在此做一个简单的记录和思路分享。希望能给大家带来帮助。 分级策略 根据拟定的评分标准&#xff0c;预生成部分已知机型的分级信息&#xff0c;且保存在包内&#xff1b;如果设备没有被评级过&#xff0c;则优…

【大厂AI课学习笔记】【2.1 人工智能项目开发规划与目标】(1)发现与明确问题

抱歉&#xff0c;过春节这几天&#xff0c;没有更新。赶紧续上。 人就是这样&#xff0c;放假之前呢&#xff0c;想着趁着这个假期&#xff0c;把很多之前没有做好的事情&#xff0c;都梳理好&#xff0c;该补的也补上&#xff0c;结果一个假期就这样过去了&#xff0c;很多想…

【探索Linux】—— 强大的命令行工具 P.22(POSIX信号量)

阅读导航 引言一、POSIX信号量的基本概念二、信号量的相关操作1 . 初始化信号量sem_init ( )&#xff08;1&#xff09;原型&#xff08;2&#xff09;参数&#xff08;3&#xff09;返回值&#xff08;4&#xff09;示例代码 2 . 等待信号量&#xff08;1&#xff09;sem_wait…

OpenCV库及在ROS中使用

OpenCV库及在ROS中使用 依赖 cv_bridge image_transport roscpp rospy sensor_msgs std_msgsCMakeLists.txt添加 find_package(OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) target_link_libraries(pub_img_topic ${catkin_LIBRARIES} ${Opencv_LIBS}) C …

【PyQt】14-绘图-QPainter

文章目录 前言一、QPainter二、绘制文本-drawTextQt里面的文本对齐方式 运行结果 三、像素点总结 前言 1、学会画图方法 一、QPainter 通常可以绘制文本、各种图形&#xff08;点、线、椭圆、弧、扇形、多边形等等&#xff09;、图像。 必须在painrEvent事件方法中绘制各种元…

win32汇编获取系统信息

.data fmt db "页尺寸&#xff1a;%d",0 db "" lpsystem SYSTEM_INFO <?> szbuf db 200 dup(0) .const szCaption db 系统信息,0 .code start: invoke GetSystemInfo,addr lpsystem …

php 函数(方法)、日期函数

php 函数、日期函数 1. php函数2. 日期函数 1. php函数 <?php// 创建一个函数 function hello($who) {echo $who.Hello World!; }hello("老张");给参数一个默认值&#xff0c;当然自己有变量走自己的 2. 日期函数 <?php/** date(Y-m-d H:i:s)返回的时间是…