【UI自动化测试】appium+python+unittest+HTMLRunner

news2024/11/25 6:45:54

进阶Python接口自动化测试必备教程(2023全网最详细)

简介

  •  获取AppPackage和AppActivity
  •  定位UI控件的工具
  •  脚本结构
  •  PageObject分层管理
  •  HTMLTestRunner生成测试报告
  •  启动appium server服务
  •  以python文件模式执行脚本生成测试报告

下载与安装

下载需要自动化测试的App并安装到手机


获取AppPackage和AppActivity

参考:https://juejin.im/post/5c3809a451882524c84ebabe

最终,得到App的信息如下:

1 appPackage:com.nbi.aquatic
2 appActivity:.ui.login.LoginActivity


定位UI控件的工具

使用Android SDK的uiautomatorviewer.bat(在..\sdk\tools\ 目录下),电脑开启开发者模式,可以使用adb命令的状态下使用该sdk自带的工具,可视化安卓手机的界面信息

★ 脚本结构

somke_test.py 存放测试集

config.py 存放自动化测试所用到的数据,如账号密码,默认密码等

pool.py等 测试集中的一个测试用例的page层

base.py 页面基础层,供page层继承

HTMLTestRunner.py 生成测试报告的模块,可集成到代码里不需在环境中安装该模块,也可在电脑python环境里安装配置
(参考:https://blog.csdn.net/weixin_38981172/article/details/82389416)


config.py 存放自动化测试所用到的数据,如账号密码,默认密码等

1 settings = {
2    'admin': {
3       'number': '13600000000',
4       'password': 'qaz123'
5    },
6    'default_password': 'a123456'
7 }
8 ADMIN_NUMBER = settings['admin']['number']
9 ADMIN_PASSWORD = settings['admin']['password']

启动app的相关配置传到appium服务端和连接手机的代码写在测试集TestCase外面,如果写在初始化测试平台的测试用例里则只能启动执行一次用例

 1 desired_caps = {}
 2 # Android自动化还是Ios自动化
 3 desired_caps['platformName'] = 'Android'
 4 # Android操作系统版本
 5 desired_caps['platformVersion'] = '5.1'
 6 # 设备名称
 7 desired_caps['deviceName'] = '127.0.0.1:62001'
 8 # 被测App包名
 9 desired_caps['appPackage'] = 'com.nbi.aquatic'
10 # 被测App的入口Activity名
11 desired_caps['appActivity'] = '.ui.login.LoginActivity'
12 desired_caps['automationName'] = 'Uiautomator2'
13 # 把以上配置传到appium服务端并连接手机
14 driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

启动app,用到的是unittest自带的setUp方法

1 def setUp(self):
2    # 初始化测试平台
3    self.driver = driver

关闭app,用到的不是unittest自带的tearDown方法,而是自定义了一个test_*_end_testing函数,这个函数负责关闭app,是在测试集里的最后一个测试用例

1 def test_36_end_testing(self):
2     """结束测试"""
3     self.driver.quit()


整体测试用例结构,采用PageObject分层管理

1.一个测试用例就是一个函数,后期增加用例时在后面增加新函数即可

2.为了使用unittest框架执行测试集,命名都以test开头,例如test_16_creat_aquatype

3.每个用例又分独立的page层,例如测试集里的用例test_16_creat_aquatype,其page层就是PoolPage,在编写测试集时引入该文件即可,也就是testcase层调用page层

 1 from appium import webdriver
 2 from test_case.page_object.admin.pool import PoolPage
 3 import unittest
 4 import config
 5 import time
 6 class SmokeTest(unittest.TestCase):
 7   def setUp(self):
 8       # 初始化测试平台
 9       self.driver = driver
10   def test_10_admin_login(self):
11       """手机登录"""
12       LoginPage(self.driver).PhoneNumberlogin_action(
13          config.ADMIN_NUMBER,
14          config.ADMIN_PASSWORD,
15      )
16   def test_16_creat_aquatype(self):
17       """添加水产类型"""
18       PoolPage(self.driver).creat_aquatype(new_aquatype_name)
19   def test_17_creat_aquatic(self):
20       """养殖池添加养殖"""
21       PoolPage(self.driver).creat_aquatic()
22   def test_36_end_testing(self):
23       """结束测试"""
24       self.driver.quit()
25 if __name__ == '__main__':
26      # 定义一个单元测试容器
27      suite = unittest.TestSuite()
28      # addTest添加case到suite容器中,构造测试集
29      suite.addTest(SmokeTest('test_10_admin_login'))
30      suite.addTest(SmokeTest('test_16_creat_aquatype'))
31      suite.addTest(SmokeTest('test_17_creat_aquatic'))
32      suite.addTest(SmokeTest('test_36_end_testing'))
33      # 执行case
34      runner.run(suite)

4.测试用例test_16_creat_aquatype的page层就是PoolPage,每个page层又都继承页面基础层BasePage

 1 from selenium.webdriver.common.by import By
 2 from test_case.page_object.base import BasePage
 3 import time
 4 class PoolPage(BasePage):
 5     """定位元素"""
 6     creataquatic_btn_loc = (By.ID, 'com.nbi.aquatic:id/tv_add_breed')
 7     select_starttime_btn_loc = (By.ID, 'com.nbi.aquatic:id/textView158')
 8     # 添加水产类型(水产名称最长10个字符)
 9     def creat_aquatype(self, aquatype_name):
10         time.sleep(3)
11         self.find_element(*self.creataquatic_btn_loc).click()
12     .......
13     # 养殖池添加养殖
14     def creat_aquatic(self):
15         self.find_element(*self.select_starttime_btn_loc).click()

5.页面基础层BasePage


 1 from selenium.webdriver.support.ui import WebDriverWait
 2 from selenium.webdriver.support import expected_conditions as EC
 3 class BasePage(object):
 4    """页面基础类,用于所有页面的继承"""
 5    def __init__(self, selenium_driver):
 6       self.driver = selenium_driver
 7       self.timeout = 30
 8       self.poll_frequency = 0.1
 9 
10    def find_element(self, *loc):
11       return self.driver.find_element(*loc)
12 
13    def find_elements(self, *loc):
14       return self.driver.find_elements(*loc)
15 
16    def content_appeared(self):
17       self.find_element()
18 
19    def wait(self, loc):
20       WebDriverWait(self.driver, 10, 0.005).until(
21       EC.visibility_of_element_located(loc)
22    )
23 
24    def wait_and_compare(self, loc, text):
25       WebDriverWait(self.driver, 30, 0.5).until(
26       EC.text_to_be_present_in_element(loc, text)
27    )


生成HTML测试结果报告

引入方式一,直接电脑python环境安装HTMLTestRunner模块

1 import HTMLTestRunner
 2 if __name__ == '__main__':
 3     suite = unittest.TestSuite()
 4     suite.addTest(SmokeTest('test_*_*'))
 5     # 写法一
 6     timestr = time.strftime('%Y%m%d', time.localtime(time.time())) # 本地日期作为报告名字
 7     filename = 'F:\\folder_data\\' # 文件名字及保存路径
 8     fp = open(filename + (timestr + '.html'), 'wb')
 9     runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='冒烟测试报告', description='用例执行情况: ')
10 
11    # 写法二
12    timestr = time.strftime('%Y%m%d', time.localtime(time.time()))
13    filename = '../_reports/' + timestr + '.html'
14    fp = open(filename, 'wb')
15    runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='冒烟测试报告', description='用例执行情况: ')
16 
17    # 执行case,并生成一份测试报告
18    runner.run(suite)
19    fp.close()

引入方式二,将HTMLTestRunner下载集成在代码内

模块下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html

 1 from packages.HTMLTestRunner import HTMLTestRunner
 2 if __name__ == '__main__':
 3     suite = unittest.TestSuite()
 4     suite.addTest(SmokeTest('test_*_*'))
 5     # 写法三
 6     fp = open('../_reports/result.html', 'wb')
 7     runner = HTMLTestRunner(stream=fp, title='冒烟测试报告', description='用例执行情况: ')
 8     # 执行case,并生成一份测试报告
 9     runner.run(suite)
10     fp.close()

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

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

相关文章

深度学习(28)——YOLO系列(7)

深度学习(28)——YOLO系列(7) 咱就是说,需要源码请造访:Jane的GitHub:在这里 上午没写完的,下午继续,是一个小尾巴。其实上午把训练的关键部分和数据的关键部分都写完了…

macOS 怎么安装redis数据库

1 访问redis数据库下载网址 http://download.redis.io/releases/ 访问上述的redis下载的网址,确定你想要的版本 然后下载即可 (我选则的是6.2.6) 然后下载 下载后 把这个文件解压,放在自己想要放在的位置 2 打开终端 输入对应的…

Hadoop 单机部署和测试(一)

Hadoop单机部署和测试 一.单机部署1.安装 JDK(JDK11)2.安装 HADOOP3.测试 一.单机部署 系统版本:cat /etc/anolis-release1.安装 JDK(JDK11) #!/bin/bashTOP_PATH$(pwd) JAVA_PATH/usr/local/java FILEls $TOP_PATH/…

本地部署 Stable Diffusion XL Gradio Demo WebUI

StableDiffusion XL Gradio Demo WebUI 0. 先展示几张 StableDiffusion XL 生成的图片1. 什么是 Stable Diffusion XL Gradio Demo WebUI2. Github 地址3. 安装 Miniconda34. 创建虚拟环境5. 安装 Stable Diffusion XL Gradio Demo WebUI6. 启动 Stable Diffusion XL Gradio De…

【LeetCode周赛】2022上半年题目精选集——动态规划

文章目录 2140. 解决智力问题解法1——倒序DP(填表法)解法2——正序DP(刷表法)⭐⭐⭐ 2167. 移除所有载有违禁货物车厢所需的最少时间⭐⭐⭐解法1——前缀和⭐⭐⭐⭐⭐解法2——前后缀分解 动态规划代码1——看了思路之后自己写的…

java中json和对象之间相互转换的运用

1.目录结构 2.配置相关文件 2.1.引入相关的pom文件 pom.xml <dependencies><!-- JSON --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.12.3</vers…

linux 基于debian_ubuntu AB系统适配(三)- overlayroot

Overlayroot Overlayroot是一个实用工具,允许您创建一个只读的根文件系统和一个可写的覆盖文件系统。这对于创建一个更安全和稳定的系统很有用,因为对系统所做的任何更改都将存储在覆盖文件系统中,可以很容易地丢弃或重置。 在Debian下,分离的系统在/userdata/rootfs_ove…

浅谈OS命令注入漏洞(Shell注入漏洞)

一、什么是OS命令注入&#xff1f; 1. 基本概念 OS&#xff08;Operating system&#xff09;命令注入&#xff08;也称为 Shell 注入&#xff09;是一个 Web 安全漏洞&#xff0c;允许攻击者在运行应用程序的服务器上执行任意操作系统 &#xff08;OS&#xff09; 命令&#…

考虑充电负荷空间可调度特性的分布式电源与电动汽车充电站联合配置方法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

DaVinci Resolve Studio 18对Mac和Windows系统的要求

DaVinci Resolve Studio 18 是一款功能强大的专业视频编辑和调色软件&#xff0c;它提供了全面的工具和功能&#xff0c;让用户能够完成从剪辑、调色到特效和音频处理等各个方面的任务。DaVinci Resolve Studio 18 在中文界面上进行了优化&#xff0c;使得中文用户能够更加方便…

【xxl-job】分布式任务调度系统xxl-job搭建

XXL-JOB是一个轻量级分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展、开箱即用。 更多介绍&#xff0c;请访问官网&#xff1a;分布式任务调度平台XXL-JOB 一、任务调度中心(基于docker)【Version 2.4.0】 前提条件&#xff1a;任务调度…

Vue3 Vite electron 开发桌面程序

Electron是一个跨平台的桌面应用程序开发框架&#xff0c;它允许开发人员使用Web技术&#xff08;如HTML、CSS和JavaScript&#xff09;构建桌面应用程序&#xff0c;这些应用程序可以在Windows、macOS和Linux等操作系统上运行。 Electron的核心是Chromium浏览器内核和Node.js…

个体化治疗策略:如何使用机器学习定制化药物?

一、引言 个体化治疗策略是一种基于患者个体特征和病情的定制化治疗方法&#xff0c;旨在提高治疗效果、减少药物副作用并优化患者的生命质量。传统的治疗方法往往采用标准化的治疗方案&#xff0c;忽视了个体差异和患者特定的需求。然而&#xff0c;每个患者的基因组、疾病特征…

JAVA——二维数组遍历二维数组的三种方法

目录 &#x1f352;java中二维数组的定义和赋值 &#x1f352;二维数组遍历的三种方法 &#x1f347;第一种&#xff1a;for循环遍历 &#x1f347;第二种方法&#xff1a;通过Arrays.deepToString()遍历 &#x1f347;第三种方法&#xff1a;通过for&#xff08; : &a…

七大排序算法——希尔排序,通俗易懂的思路讲解与图解(完整Java代码)

文章目录 一、排序的概念排序的概念排序的稳定性七大排序算法 二、希尔排序核心思想代码实现 三、性能分析四、七大排序算法性能对比 一、排序的概念 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0…

自动化测试与持续集成方案

目录 前言&#xff1a; 传统接口测试 接口测试自动化 接口自动化的持续集成 前言&#xff1a; 自动化测试和持续集成是软件开发过程中非常重要的环节。自动化测试可以提高测试效率和准确性&#xff0c;而持续集成则可以确保代码的稳定性和可靠性。 传统接口测试 不知道别…

使用WiFi测量仪进行机器人定位的粒子过滤器研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

50. Pow(x, n) 快速幂

题目链接&#xff1a;力扣 解题思路&#xff1a;直接使用for进行累乘会超时&#xff08;时间复杂度O(n)&#xff0c;n为指数n的大小&#xff09;&#xff0c;可以使用快速幂进行更快的幂运算(时间复杂度为O(logn)) 快速幂&#xff1a;核心思想就是每一次把指数缩小一半&#x…

华南农业大学|图像处理与分析技术综合设计|题目解答:读取电表示数

l 设计任务&#xff1a; ipa05.jpg是一幅电气柜上的电表图像&#xff0c;试采用图像处理与分析技术&#xff0c;设计适当的 算法和程序&#xff0c;找出电流表所在的区域&#xff0c;提取其指针位置&#xff0c;计算指针与表盘下沿 的夹角&#xff0c;进而判断当前电表的读数…

车载软件架构——车载诊断软件框架

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 人们会在生活中不断攻击你。他们的主要武器是向你灌输对自己的怀疑&#xff1a;你的价值、你的能力、你的…