seldom 实战技巧

seldom 是我一直在维护的自动化测试框架。目前GitHub已经 500+ star。

最近在项目中使用Seldom + poium 编写自动化测试用例。接下来,我就分享一些使用技巧。

如何参数化测试用例

网站的首页,如上面的导航。于是,开始利用poium编写元素定位。

from poium import Page, Elementclass Homepage(Page):destination_hk = Element(cass='#id_2&ext', describe="探索目的地-香港")destination_macau = Element(css='#id_3&ext', describe="探索目的地-澳门")destination_singapore = Element(css='#6&ext', describe="探索目的地-新加坡")...

写着写着,我发现这样的用例不可维护,因为这里的导航是由后台配置出来的一个导航,热门目的地不是固定的,随国家、语言变化。

修改用例如下:

# page
from poium import Page, Elementsclass Homepage(Page):destination_all = Elements(xpath='//div/div/', describe="所有热门城市")# case
import seldomclass TestHomeNav(seldom.TestCase):"""导航"""def start(self):self.open("https://www.shop.com/")self.hp = HomePageCN(self.driver)def test_nva_search(self):# 遍历城市列表,点击每一个城市destinations = self.hp.destination_allfor elem in destinations:elem.click()

那新的问题来了,这么写就一条用例,而且,假设其中一个城市配置链接错误或失效,整个用例失败,我们很难排查是哪个城市的问题,而且也不利于用例统计。

最后,改进之后的方案。

# page
from poium import Page, Elementsclass Homepage(Page):destination_all = Elements(xpath='//div/div/', describe="所有热门城市")# common
def get_destinations_data(url):"""获得热门目的地的 数量:return: [(),()]"""hp = HomePage(Seldom.driver)hp.open(url)destinations = hp.destination_alldestinations_data = []for i, elem in enumerate(destinations):destinations_data.append((elem.text, i))return destinations_data# case
import seldom
from seldom import database_url = "https://www.shop.com/"class TestHomeNav(seldom.TestCase):"""导航"""def start(self):self.open(base_url)self.hp = HomePage(self.driver)@data(get_destinations_data(base_url))def test_nva_search(self, name, i):# 探索目的地print("city name-->", name)destinations = self.hp.destination_allcity_name = destinations[i].textdestinations[i].click()self.assertText(city_name)

这种方案有两个好处。

  1. 城市列表变动,不会影响用例的执行。
  2. 每个城市统计一条用例。

seldom基于unittest的参数化非常简单和强大,这也是我没有转投pytest的最主要原因之一。 pytest的参数化@pytest.mark.parametrize()确实不好用,这一点不接受反驳。

用例依赖

这一条用例是我要自动化点击搜索历史搜索历史搜索过​才会产生的数据。

# case
import seldom
from seldom import data
from seldom import dependclass TestHomeSearch(seldom.TestCase):"""搜索"""def start(self):self.open(base_url)self.hp = HomePage(self.driver)@data([("case1", "迪士尼"),("case2", "双月湾"),("case3", "上海"),])def test_search_a_keyword(self, name, keyword):"""搜索:活动、城市"""print("case name-->", name)self.hp.search_input.send_keys(keyword)self.hp.search_button.click()self.assertText(f"以下是与“{keyword}”相关的体验")@depend("test_search_a_keyword")def test_search_history(self):"""搜索:点击搜索历史"""history = self.hp.search_historykeyword = history[0].texthistory[0].click()self.assertText(f"以下是与“{keyword}”相关的体验")
  1. 搜索再次用到了参数化。
  2. 通过@depend() 装饰器设置依赖上面的用例test_search_a_keyword,当被依赖的用例失败时,该用例直接跳过。

UI + 接口自动化混搭验证

Seldom既支持Web UI自动化,又支持接口。

例如,上面的活动卡片,如何验证图片是否显示。

  • 截图对比
    1. 提前准备一张对比的图片,太麻烦,存在对比偏差,活动有被替换的风险。
    2. 自动截图,人工检查截图,这不叫完全自动化。
    3. 跑自动化的时候,测试人员盯着看... 这就很离谱了。
<img src="https://gimg2.baidu.com/i/eg_tulip.jpg"  alt="雪山" />

先来看看一张图片的定义。如果一张图片无法显示。

  1. html 代码写错,例如 src 写成 scr
  2. 图片链接失效。

第一种情况概率很低,而且很容易发现,而且是必现。第二种情况就比较麻烦了,可能图片链接一开始是好的,可能因为图片服务器问题导致图片丢失。

好了,分析完图片不可见的情况。那么就可以通过验证图片请求来保证图片是可见的。

import seldomclass TestHomeActivity(seldom.TestCase):def start(self):self.open(base_url)self.hp = HomePageCN(self.driver)def test_hot_sale_activity(self):"""检查活动活动 图片"""img = self.hp.activity_img.get_attribute("src")self.get(url=img)  # 调用图片链接self.assertStatusCode(200)  # 断言活动图片是否可以访问

通过get_attribute() 获取元素的src 图片链接,然后,直接self.get()调用图片地址,如果返回200 说明图片可访问。

是不是web UI和 接口自动化无缝连接。

最后:

https://github.com/SeldomQA/seldom

提供一下GitHub地址,如果有GitHub帐号,欢迎+ star,最近在使用过程中也在更加积极的完善功能和修复bug。如果你正在开展自动化测试,不妨试试Seldom,他降低了你自己搭建自动化测试项目的成本,提高你编写和维护用例的速度。

行动吧,在路上总比一直观望的要好,未来的你肯定会感 谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入扣群: 320231853,里面有各种软件测试+开发资料和技术可以一起交流学习哦。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

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

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

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

相关文章

Leetcode 3098. Find the Sum of Subsequence Powers

Leetcode 3098. Find the Sum of Subsequence Powers 1. 解题思路2. 代码实现 题目链接&#xff1a;3098. Find the Sum of Subsequence Powers 1. 解题思路 这一题思路上的话还是比较直接的&#xff0c;由于我们只需要求出每一个可能的power值&#xff0c;然后求出对应的po…

GitHub常用命令

GitHub常用命令 远程仓库相关命令拉取项目到本地拉取远程仓库推送远程仓库 分支操作相关命令查看所有本地分支查看所有远程分支查看所有本地分支和远程分支切换分支创建本地分支创建远程分支(本地分支push到远程)创建新分支并切换到新分支合并指定分支到当前分支删除分支 代码提…

基于 FFmpeg 和 SDL 的音视频同步播放器

基于 FFmpeg 和 SDL 的音视频同步播放器 基于 FFmpeg 和 SDL 的音视频同步播放器前置知识音视频同步简介复习DTS、PTS和时间基 程序框架主线程解复用线程音频解码播放线程视频解码播放线程 音视频同步逻辑源程序结果工程文件下载参考链接 基于 FFmpeg 和 SDL 的音视频同步播放器…

蓝桥杯备考随手记: Math 类中常用方法

Java的Math类是一个包含数学操作方法的实用工具类。它提供了许多用于执行各种数学计算的静态方法。 下面是Math类中一些常用的方法&#xff1a; abs()&#xff1a;返回参数的绝对值。 int absoluteValue Math.abs(-10); System.out.println(absoluteValue); // Output: 10 c…

EtherCAT主站SOEM -- 25 -- STM32F767-SOEM通过 PV模式(速度模式)控制一个电机转圈圈

EtherCAT主站SOEM -- 25 -- STM32F767-SOEM通过 PV模式(速度模式)控制一个电机转圈圈 0 QT-SOEM视频预览及源代码下载:0.1 QT-SOEM视频预览0.2 QT-SOEM源代码下载0.3 STM32F7-SOEM视频预览0.4 STM32F7-SOEM源代码下载1 程序文件修改替换1.1 allvalue.h1.2 allvalue.c1.3 mot…

BaseDao入门使用

目录 一、什么是BaseDao?BaseDao的优点&#xff1a;BaseDao用来做什么操作&#xff1f; 二、BaseDao封装增删改查 案例演示&#xff1a;1、java与数据库进行连接2、连接后可对其进行操作&#xff08;增、删、改&#xff09;返回影响行数3、查询 查询一个字段&#xff08;返回一…

python基础练习题6

1、找出10000以内能被5或6整除&#xff0c;但不能被两者同时整除的数&#xff08;函数&#xff09; def find_numbers(m,n):result []for num in range(m,n):if (num % 5 0 or num % 6 0) and not (num % 5 0 and num % 6 0):result.append(num)return resultprint(find_…

Linux: 进程优先级

Linux: 进程优先级 一、进程优先级概念二、如何查看进程优先级三、如何修改进程的优先级&#xff08;PRL vs NI&#xff09;四、为何优先级PRL必须限定范围五、进程其他特性 一、进程优先级概念 优先级的本质就是排队&#xff0c;而排队则是资源不足所引起的。在计算机中&#…

static修饰的方法为什么不能被覆盖?

在Java中&#xff0c;static方法不能被覆盖&#xff08;overridden&#xff09;的根本原理可以从以下几个角度进行解释&#xff1a; 静态绑定与动态绑定&#xff1a; 非静态方法&#xff08;非static方法&#xff09;的调用遵循动态绑定原则&#xff0c;即在运行时根据对象的实…

分布式系统概述(重要关键词加粗)

学习目标&#xff1a; 了解分布式 学习内容&#xff1a; 分布式系统是由多个计算机节点组成的系统&#xff0c;这些节点通过网络相互连接并协同工作&#xff0c;以完成共同的任务或服务。在分布式系统中&#xff0c;每个节点都运行着一部分应用程序&#xff0c;并且通常拥有自…

Leetcode 3100. Water Bottles II

Leetcode 3100. Water Bottles II 1. 解题思路2. 代码实现 题目链接&#xff1a;3100. Water Bottles II 1. 解题思路 这一题就是按照题目翻译一下&#xff0c;按照题中给出的规则不断进行bottle的兑换&#xff0c;直至无法兑换为止&#xff0c;即可得到最终的答案。 2. 代…

【3.31】

智乃想考一道完全背包(Easy version) 思路&#xff1a;虚拟物品的思路。可以把 l ∈ [ 1 , k ] , r ∈ [ k , n ] l\in[1, k], r\in[k, n] l∈[1,k],r∈[k,n] 的区间 ( l , r ) (l, r) (l,r) 看作一个虚拟物品&#xff0c;体积和价值为区间的体积和与价值和。这样做完全背包…

【项目技术介绍篇】若依开源项目RuoYi-Cloud前端技术介绍

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过大学刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0…

鸿蒙ARKTS--简易的购物网站

目录 一、media 二、string.json文件 三、pages 3.1 登录页面&#xff1a;gouwuPage.ets 3.2 PageResource.ets 3.3 商品页面&#xff1a;shangpinPage.ets 3.4 我的页面&#xff1a;wodePage.ets 3.5 注册页面&#xff1a;zhucePage.ets 3. 购物网站主页面&#xff…

STM32学习笔记(10_2)- I2C通信协议MPU6050简介

无人问津也好&#xff0c;技不如人也罢&#xff0c;都应静下心来&#xff0c;去做该做的事。 最近在学STM32&#xff0c;所以也开贴记录一下主要内容&#xff0c;省的过目即忘。视频教程为江科大&#xff08;改名江协科技&#xff09;&#xff0c;网站jiangxiekeji.com 本期开…

[Linux_IMX6ULL驱动开发]-基础驱动

驱动的含义 如何理解嵌入式的驱动呢&#xff0c;我个人认为&#xff0c;驱动就是嵌入式上层应用操控底层硬件的桥梁。因为上层应用是在用户态&#xff0c;是无法直接操控底层的硬件的。我们需要利用系统调用&#xff08;open、read、write等&#xff09;&#xff0c;进入内核态…

synchronized的使用方式

1、修饰实例方法 public synchronized void A(){} 这个时候锁的是当前的实例对象。多线程操作同一个实例的实例方法时&#xff0c;才会阻塞。 2、修饰静态方法 public synchronized static void A(){}这个时候锁的是整个类下所有的实例对象&#xff0c;静态方法是存在于方法…

自然语言处理:大模型LLM论文整理

LLMs 九层妖塔 地址&#xff1a;https://github.com/km1994/LLMsNineStoryDemonTower LLMs 千面郎君 地址&#xff1a;https://github.com/km1994/LLMs_interview_notes LLMs 论文学习笔记&#xff1a;https://gitee.com/km601/llms_paper NLP 百面百搭 地址&#xff1a;htt…

os模块篇(三)

文章目录 os.putenv(key, value, /)os.setegid(egid, /)os.seteuid(euid, /)os.setgid(gid, /)os.setgroups(groups, /)os.setns(fd, nstype0)os.setpgrp()os.setpgid(pid, pgrp, /)os.setpriority(which, who, priority) os.putenv(key, value, /) os.putenv(key, value) 是 …

看懂Spring和Spring Boot的区别与联系

一、概述 Spring和Spring Boot是Java应用程序开发中最受欢迎的框架之一。Spring提供了一个全功能的、开放式源代码的Java应用程序框架&#xff0c;可以帮助开发人员在基于Java的代码中快速编写而不必关心底层技术实现。而Spring Boot则是基于Spring框架之上的快速开发框架&…