web自动化测试入门篇07 ——— 用例编写技巧

news2024/11/25 4:27:34

在这里插入图片描述

 
 

在这里插入图片描述
😏作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。
📡主页地址:【Austin_zhai】
🙆目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能,分享行业相关最新信息。
💎声明:博主日常工作较为繁忙,文章会不定期更新,各类行业或职场问题欢迎大家私信,有空必回。

在这里插入图片描述

 
 

阅读目录

  • 1. 目的
  • 2. 编写的基础原则
    • 2.1 用例的简洁、清晰
    • 2.2 用例的可重复性
    • 2.3 用例的覆盖率
    • 2.4 确保测试用例可维护性
  • 3. 用例编写技巧
    • 3.1 步骤拆解
    • 3.2 模块化
    • 3.3 参数化
    • 3.4 数据驱动
    • 3.5 断言
      • 3.5.1 assertAlmostEqual
      • 3.5.2 assertRegex

1. 目的

在这里插入图片描述

  web自动化测试作为软件自动化测试领域中绕不过去的一个“香饽饽”,通常都会作为广大测试从业者的首选学习对象,相较于C/S架构的自动化来说,B/S有着其无法忽视的诸多优势,从行业发展趋、研发模式特点、测试工具支持,其整体的完整生态已经远远超过了C/S架构方面的测试价值。

  截止现在,我们已经学习了web自动化测试的大部分基础内容,有了之前的这些知识与实践,我们已经可以大致将一个web自动化脚本写出来了,那么在我们执行脚本之前,还有一个比较重要的部分,那就是自动化测试用例,这个可以说是我们整个测试用最最至关重要的部分了,没有了它自动化测试的基准也会变得混沌不清,所以如何写好自动化中的测试用例直接决定了你的自动化测试的落地价值与执行意义。

 
 

2. 编写的基础原则

在这里插入图片描述
  我们在动手转化或编写自动化测试用例之前,需要先搞清楚几件事情,无论是从手工测试中转化还是重新设计,都推荐遵循以下几条原则,这些和我们的黑盒测试的设计原则相近。

 

2.1 用例的简洁、清晰

  自动化测试用例的意图应该易于理解和解释。每个测试用例应该只关注一个特定的功能或场景,以确保测试结果的清晰和易于解释。这里的功能与场景可以理解为在自动化测试执行中需要验证的是单个功能点还是一组业务流程,这个和黑盒测试的测试用例有点区别,正是因为自动化测试的特性,可以帮助测试在极短的时间内对某个所需测试的业务流进行验证,所以使用测试用例来验证一些重复的业务场景正是自动化测试的价值体现。

 

2.2 用例的可重复性

  自动化测试用例应该可以重复执行,这个与黑盒用例的设计理念一致,我们在日常的黑盒测试结束以后都会将测试用例补全或优化,方便之后的迭代版本再次复用或回归重组。那么在自动化测试用例中,用例的重复利用也就变的顺理成章了。当然,虽然理念相同,但实际设计与操作起来还是有些区别的,比如自动化测试用例在设计的时候要考虑测试数据的生成与回收。

 

2.3 用例的覆盖率

  覆盖率永远是测试活动中的永恒课题之一,如何拥有良好的覆盖率也是广大测试人员的争论不休的话题,针对自动化测试,大家要清楚,覆盖率的认知与黑盒测试的不同,这里仍然是基于自动化测试的特性,覆盖的范围与覆盖率应当遵从各自团队自动化测试的需求与项目痛点来进行定义, 不能一概而论,比如A公司的自动化测试解决的是回归测试人手不足的问题,那么覆盖范围与覆盖率应集中在主业务的happy path上,过多的业务分支将会产生过多的自动化脚本与测试用例,同时也会间接的提升人员的时间成本与维护效率 。如果版本质量不佳,但人员较为充足,自动化的覆盖率与范围可以适当的提升,将一些常见的异常场景与次级重要的业务线加入其中,可以有效的降低人员测试失误或漏测的现象发生。

 

2.4 确保测试用例可维护性

  自动化测试用例应该易于维护,这句话该如何理解呢?其实作为自动化测试脚本的一部分,测试用例的维护往往直接体现在它的设计结构,在我们编写自动化测试用例的时候,同样应当考虑后续的维护难易度,这里就比较推荐模块化的设计理念,用例之间不应该存在强耦合,直接的数据依赖等因素,这样会影响用例的模块化,较为良好的模块化测试用例可以有效提升后期的用例维护难度与降低用例重组、更新升级的难度。

 
 

3. 用例编写技巧

在这里插入图片描述
  说了那么多,接下来就让我们来进入实际编写的环节吧,在编写的同时我们将逐步理解其中的一些编写技巧与操作理念。

 

3.1 步骤拆解

  我们在编写自动化测试用例的时候,可以根据业务功能模块的操作特点将测试用例里的业务操作分割成多个步骤,每个步骤必须有明确的操作行为,如此我们就可以精确的控制测试用例执行时候的测试过程,也贴合了高可维护性的设计基础原则。

  拿PO模式的UI测试框架来说,如果我们要测试一个登录页面,首先的元素定位操作大家都可以理解,那元素定位之后我们需要做什么呢?其实光有元素定位肯定是不够的,我们还需要对应的业务操作。业务操作的封装也是见仁见智,有的在PO中封装,有的在用例中直接操作。但这不影响我们今天要说的这个主题,在我们编写测试用例的时候,依照步骤拆解的技巧,我们可以把登录功能的验证点划分为:

✔️打开登录页面
✔️ 输入用户名
✔️ 输入密码
✔️ 点击登录按钮
✔️ 验证登录是否成功

  如上可见,步骤拆解的目的就在于它将一个完整的测试用例业务操作拆成了多个测试步骤,我们可以单独对每一个步骤进行代码设计,最后将其组合程一个完整的用例,这样设计出的用例在阅读与维护方面就会有较大的提升。

 

3.2 模块化

  模块化也是设计自动化测试用例中非常重要的一块内容,这个从根本上来说与面向对象的编程理念是相同的,说人话就是将一些需要经常用到的业务操作与功能模块进行模块化,以便后续的业务操作直接复用。比如我们日常中最常见的用户注册与登录、登出、某些模板的增删改查等功能。

 

3.3 参数化

  参数化测试也是目前比较主流的一种用例设计方式,它的本质就是可以在测试用例中使用不同的参数进行多次执行测试。这对于相似的测试场景非常有用,可以大大简化测试用例的编写。也就相当于在一个测试用例中执行了多次,但每一次的参数都是不同的。对一些较大的边界值,输入类组件,条件较多的排列组合的场景特别的适用。

这里以unittest来举例说明,参数化在这个库中可以使用subTest()方法类进行实现。

import unittest
from selenium import webdriver

class LoginTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()

    def tearDown(self):
        self.driver.quit()

    def test_login(self):
        data = [
            {'username': 'user1', 'mpd': 'pwdmpd1'},
            {'username': 'user2', 'mpd': 'pwdmpd2'},
            {'username': 'user3', 'mpd': 'pwdmpd3'},
        ]

        for d in data:
            with self.subTest(username=d['username'], password=d['password']):
                self.driver.get('http://localhost/login')
                self.driver.find_element_by_name('username').send_keys(d['username'])
                self.driver.find_element_by_name('password').send_keys(d['password'])
                self.driver.find_element_by_css_selector('button[type="submit"]').click()

                # assert login success
                self.assertTrue(self.driver.current_url.endswith('/dashboard'))

if __name__ == '__main__':
    unittest.main()

在上面的代码中,我们使用了一个字典列表来保存不同的用户名和密码组合。然后使用for循环来遍历这个列表,并使用subTest()方法来为每组数据生成一个独立的测试用例。这样就可以在测试报告中看到每个数据的测试结果,方便排查问题。

 

3.4 数据驱动

  数据驱动和之前的参数化是不同的两个概念,数据驱动是更加完整的数据测试的体现,它将测试数据和测试逻辑分离,将测试数据存储在外部数据源中,然后使用程序来读取测试数据并执行测试。这里的数据源可以是多种多样的,具体是文件还是持久化则根据各自公司的业务来决定。

同样的,我们可以使用pandas这个三方库来实现DDT,假设我们有这样一份数据文件,里面保存了被测对象的用户名和密码。

usern,psswd
u-test1,pwd1
u-test2,pwd2
u-test3,pwd3

然后,我们封装一个test_data_load函数,用来读取这个CSV文件,并将每行数据转换成一个字典对象。
这个函数会返回一个字典列表,每个字典对应一行数据,字典的key对应CSV文件的列名,value匹配对应列的值。

import pandas as pd

def test_data_load(file):
    data = pd.read_csv(file)
    return data.to_dict('records')

我们在测试用例中使用这个函数来读取测试数据,并使用for循环来遍历每个数据执行测试。

import unittest
from selenium import webdriver
from test_function import load_test_data

class LoginTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()

    def tearDown(self):
        self.driver.quit()

    def test_login(self):
        test_data = load_test_data('test.csv')
        for data in test_data:
            username = data['username']
            password = data['password']

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


if __name__ == '__main__':
    unittest.main()

 

3.5 断言

  最后我们还是要来说一说断言,测试用例中作为判断测试结果是否符合预期结果的重要方式之一,我们有足够的理由在断言上下大功夫来设计此部分。今天介绍给大家的不单单是一些基础的断言方式,为了使我们的测试断言更加的完善与多样化,我们还需要利用断言的各种其他方法来进行更加精准的结果判断。

3.5.1 assertAlmostEqual

  assertEqual,想必大家已经很熟悉了,一般的结果判断都会用此方法来断言。那么assertAlmostEqual又是什么呢?这个断言方法是用来对比浮点数对象是否大致相等的。为什么是大致呢?其实写过代码的同学应该都清楚,在代码中小数的位数不单单只是后两位这么简单,包括小数的计算也是较为复杂的,所以这里我们只需要运用这个特性,在需要对比的小数位的基础上多对比几位即可达到我们要的效果。

class TestMath(unittest.TestCase):
    def test_divide(self):
        result = 3.0 / 2
        self.assertAlmostEqual(result, 1.5, places=3, msg='除法的结果不正确。')

我们来看下这个断言方法所带的参数的大致含义,第一个和第二个是要对比的数值,第三个places是一个可选参数,它是需要对比的小数位,默认为7,也就是对比到第七位。所以在不指定位数的情况下:

self.assertAlmostEqual(0.5, 0.4) return false
self.assertAlmostEqual(0.12345678, 0.12345679) return true

msg则是断言失败后的提示内容。

 

3.5.2 assertRegex

  assertRegex是用正则表达式的方式来进行对象结果断言的方法,也正是因为有正则表达式的存在,让很多的内容格式场景有可以用上这个断言,比如我们最熟悉的邮箱格式验证、手机格式验证等。

邮箱格式验证

class TestString(unittest.TestCase):
    def test_email_validation(self):
        email = 'test_center@test.com'
        regex = r'^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$'
        self.assertRegex(email, regex, msg='邮箱格式错误。')

手机格式验证

import re
import unittest

class TestMobile(unittest.TestCase):
    def test_valid_mobile(self):
        pattern = re.compile(r'^1[3-9]\d{9}$')
        valid_mobiles = ['13112345678', '13912345678', '14712345678']
        for mobile in valid_mobiles:
            with self.subTest(mobile=mobile):
                self.assertTrue(pattern.match(mobile), msg=f"{mobile} 是无效手机号")

 

  当然除了这两个之外还一些其他的断言方式,比如assertJsonEqual、assertLogs、assertCountEqual等,但这些都不太适合在UI自动化测试中进行断言使用,所以就不做详细的介绍了。大家在日常的设计编写工作中如果可以按照上述的这些原则与技巧进行执行,相信设计出来的测试用例一定会有效的提升后续对应测试的工作效率。

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

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

相关文章

idea中导入spring源码错误during working with external system: java.lang.AssertionError

标题:idea中导入spring源码错误during working with external system: java.lang.AssertionError 1.Spring源码编译环境 spring 5.3.1 JDK环境:1.8 Spring版本:5.3.1版本 开发工具:IntelliJ IDEA 2019.10 编译工具:Gradle-6.4-bin 操作系统:windows 10 注: sprin…

分支和循环语句(2)

文章目录 3.2 for循环3.2.1 for语句的语法3.2.2 for循环中的break和continue3.2.3 for语句的循环控制变量3.2.4 一些for循环的变种3.2.5 一道笔试题 3.3 do while循环3.3.1 do语句的语法3.3.2 do语句的特点3.3.3 do while循环中的break和continue 3.4 练习3.4.1 计算 n的阶乘3.…

数据可视化工具汇总:数字孪生产品的得力助手

数字孪生技术是一项快速发展的新兴技术,已经在许多领域得到广泛应用。数字孪生技术不仅可以提供完整的虚拟模型,还可以模拟物理系统的行为。在数字孪生技术的推动下,越来越多的数字孪生产品开始涌现出来,为不同的领域提供支持和解…

2023年保理产品研究报告

第一章 行业概况 1.1 概述 保理(Factoring),全称保付代理,又称托收保付,是一种通过将企业的应收账款出售给专业金融机构(保理公司)来获得资金的融资方式。保理业务通常包括两种类型&#xff1…

数据治理:解决一物多码,多品牌食品集团主数据管理实践

浙江顶誉集团是一家知名的食品加工集团,拥有久久丫、留夫鸭等多个品牌。一直重视企业信息化建设,更是把数字化作为集团的一大发展方向,立志不断加大数字化投入和建设,成为一个数字化的企业。因此,该企业与亿信华辰合作…

如何通过FAQ页面减轻客户支持压力,提高工作效率?

作为现代企业不可或缺的一部分,客户支持服务是为客户提供解决方案、回答问题和解决技术难题的关键部分。无论是产品管理还是销售环节,客户支持都是重要的一环。然而,有效地处理技术支持问题和客户请求并不容易。卓越的客户支持需要组织结构&a…

CCFC22102B 时钟分析

CCFC2012BC基于国芯科技自主PowerPC架构C*Core CPU内核研发,是一款汽车电子中高端车身及网关控制芯片,可广泛应用于车身控制和网关以及新能源车的整车控制,实现对国外产品如NXP(恩智浦)MPC5604BC、MPC5607B系列以及ST的…

Seurat -- variable features select

brief seurat提供的教学里面包含了Standard pre-processing workflow,workflow包括QC,normalization,scale data ,detection of highly variable features。其中 normalization就有蛮多方法的,seurat自己就提供了两种&#xff0c…

OpenGL入门教程之 坐标系统

原文文章 原文链接  本文仅对有代码的地方做讨论。 投影矩阵 创建一个正射投影矩阵 glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);第一二个参数指定了平截头体的左右坐标,第三四个参数指定了平截头体的底部和上部,第五六个参数指定了近平面…

idea基于docker插件部署docker服务

IDEA开发完项目,直接部署至docker上镜像运行,接下来开始体验吧 注意:假定您的项目开发完了,假定你准备好了docker服务哈 没安装docker的来抄作业(docker的安装) 我的docker所在宿主机的内网ip:1…

银行卡识别OCR:解放金融业务处理效率的黑科技

引言 随着移动支付和电子商务的快速发展,人们越来越依赖银行卡进行交易。而银行卡信息的识别和处理也变得越来越重要。传统的手动输入银行卡信息方式效率低下且容易出错,而采用银行卡识别OCR 技术可以实现快速自动识别银行卡信息,极大地提高…

git把一个分支上的某次修改同步到另一个分支上,并解决git cherry-pick 冲突

背景 我们在工作中经常会碰到好几个同事共同在一个分支上开发,一个项目同时会有好几个分支,我们在feature上开发的功能时,有可能某个需求需要提前发布,这个时候我们已经在feature A上开发完成,但是需要在master上发布…

解锁阿迪达斯营销姿势,分析阿迪达斯成功背后的营销策略

阿迪达斯品牌在1920年创立于德国的运动品牌制造商——著名企业家阿道夫达斯勒,并且当年就开始生产该品牌的鞋类。如今,阿迪达斯已经象征着运动时尚的潮流品牌,在世界的舞台上大放异彩。因此阿迪达斯的营销策略一直备受关注,今天我…

乌合之众再次上演,打工人将被AI一键淘汰?

ChatGPT,是一场以硅谷为圆心,辐射至全球的人工智能竞赛,人们关于人工智能的担忧与思考从未停歇。一起来看看这篇文章,了解一下——大浪来袭,要怎么做才能保证自己不会溺水? 上个月底,千余名科技…

盛元广通病原微生物保藏信息管理系统

目前现状 微生物菌种是宝贵的生物资源,对微生物学研究和微生物资源开发与利用具有非常重要的价值。所以菌种的分类及保藏非常重要。当前,大部分实验室仍采用传统人工方式来管理和保藏病原微生物样本信息,不仅效率低下,且耗费大量人…

回溯/DFS算法专题

回溯/DFS算法专题 框架篇全排列问题N 皇后问题如果只需要一个合法答案,怎么办? 排列组合问题子集(元素无重不可复选)LeetCode 78. 子集解题思路代码实现 组合(元素无重不可复选)LeetCode 77. 组合解题思路代…

迅为iTOP-i.MX6ULL开发板I2C驱动程序实现 I2C通信

在第 67.1 章节学习 i2c 的时候,我们是在应用层操作设备节点对 i2c 设备进行读写的,那么如果我们在 驱动里面对 i2c 设备进行读写要怎么办呢?本章节我们将来学习。 我们复制第 67.3 章节的代码,在此基础上进行修改。我们在应用里…

gis几种常用插值介绍

反距离权重法(距离加权法)简称IDW: 这个方法的原理简单来说就是插值点距离已知点的距离越远受影响的程度越低,下图中的黄点为已知点,红点为插值点,那这个距离是如何控制的? 反距离权重法主要依…

基于SGM431的电路设计问题分析

本案例中,采用SGM431芯片设计了一个过压保护电路。 这个电路初次设计,有很多的问题,下面逐一分析 1.当输入24V,测得Vref=1.59V。Vout为1.15V;,mos管关断 2。经过多次测量发现,临界值在10V到10.5之间; 当输入10.5V时,测量Vref=1.69V。vout=1.15V;mos管关断 当输入1…

存储过程批量修改数据库中部分表中的ip信息

一、背景 项目中涉及到环境迁移,迁移过程中,原来的数据库(oracle)中应用ip和数据库ip地址均未变更,每次都是手动修改,想通过存储过程快捷执行 二、修改目标: 把相关几个表格的ip地址变更为其…