前言

Toast是什么呢?在这个手机飞速发展的时代,app的种类也越来越多,那们在日常生活使用中,经常会发现,当你在某个app的输入框输入非法字符或者非法执行某个流程时,经常看到系统会给你弹出一个黑色的提示框,告诉你你的操作不合法,比如某个app的登录流程,当你输入错误的用户名时,系统会弹出一个框提示你:用户名不正确,请重新输入;并且这个提示框往往会很快消失,并不需要用户自己执行关闭操作,其实这个弹框就是Toast

定位Toast的条件

定位toast及操作toast之前,你需要确保你的自动化测试环境应该满足以下条件

1.你的app自动化测试环境本身没有问题,能够成功执行自动化测试代码

2.appium server的版本应该在1.6以上(最好直接安装最新的版本,避免不必要的麻烦)

你可以参考我这篇关于appium环境搭建的文章,在写这篇文章时,我下载的就是比较老的版本,导致我后来定位toast时,一直定位不到,找了好半天原因,我一直以为我安装的是最新版的,其实并不是,罪魁祸首就是下载appim desktop时的地址不是官方的地址,当然之前的文章我也已经做了更新,避免你们遇到和我一样的问题

3.Toast是无法通过定位工具成功定位到的,所以你需要了解selenium中显示等待方法presence_of_element_located的作用(注意这里之只能使用这个方法,别的方法都无法定位到)

4.初始化driver时的参数需要指定automationName为UiAutomator2

Toast定位表达式

Toast虽然无法通过定位工具定位,但是几乎所有的toast都有一段文本,根据我们以往的经验,这段文本内容应该就是toast的text属性值,因此我们可以通过text属性结合xpath模糊定位的方式来定义toast的表达式,如果你对xpath有一定的了解,那么对这个表达式的意义应该不难理解: "//*[contains(@text, '{}')]".format("toast文本值")

需要说明一点,这里的@text代表的是toast的text属性(比如说它还有resource-Id属性),请区分web定位某一个元素时使用的定位表达式//*[contains(text(), '文本值')]

测试代码

定位表达式有了,再结合显示等待的presence_of_element_located方法,我们来编写一段测试代码测试一下是否能够成功定位到toast并获取他的文本值

"""
------------------------------------
@Time : 2019/8/12 20:28
@Auth : linux超
@File : test_toast.py
@IDE : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ : 28174043@qq.com
@GROUP: 878565760
------------------------------------
"""
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait def wait_present_element(locator):
return WebDriverWait(driver, 20, 0.01).until(ec.presence_of_element_located(locator)) def wait_clickable_element(locator):
return WebDriverWait(driver, 20, 0.01).until(ec.element_to_be_clickable(locator)) desired_caps = {
"automationName": "UiAutomator2",
"platformName": "Android",
"platformVersion": "5.1.1",
"deviceName": "127.0.0.1:62001",
"appPackage": "com.xxzb.fenwoo",
"appActivity": "com.xxzb.fenwoo.activity.addition.WelcomeActivity"
}
# 初始化driver
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps)
# 直接跳到指定页面
driver.start_activity("com.xxzb.fenwoo", ".activity.addition.FillPhoneActivity")
# 输入用户名
wait_present_element((MobileBy.ID, "com.xxzb.fenwoo:id/et_phone")).send_keys("")
# 点击下一步
wait_present_element((MobileBy.ID, "com.xxzb.fenwoo:id/btn_next_step")).click()
# 定位toast
toast = wait_present_element((MobileBy.XPATH, "//*[contains(@text, '{}')]".format('无效的手机号码')))
# 获取toast的文本值
# context = toast.text
context = toast.get_attribute("text")
print("toast的文本值为", context)
# 关闭driver
driver.quit()

输出

toast的文本值为无效的手机号码

Process finished with exit code 0

ok, 这段代码成功输出了toast的文本值,那么在自动化测试的时候,我们就可以通过文本值来做一些断言了

代码优化

你会发现上面的测试代码完全是流水式的编程方式,实际工作中几乎不会允许你出现这样的代码,虽然今天的主题是如何处理toast,无关代码写的好与不好,也无关代码的编程思想,但是我想说的是所有的代码书写规范和编程思想都是日积月累的养成的,并不是一朝一夕就能掌握的,而且我也希望看到我文章的人不仅仅只学到简单的用法,除此之外还能学到一些编程思想和小技巧,还是那句话希望在你成功的道路上有我的身影!

废话说了这么多,我们需要做的就是模块化,把一些代码中能够分离出来的部分,能够重复调用的部分进行分离,比如查找某一个元素,等待某个元素能点击,等待某个元素出现,向某个输入框中输入值等,还有就是把所有的操作尽量结合显示等待来操作,这样可以增加脚本的稳定性,并且对于toast的定位我们也需要封装成一个通用的方法,通过传递不同的文本值,达到定位不同toast的目的

封装代码

"""
------------------------------------
@Time : 2019/8/12 8:45
@Auth : linux超
@File : base.py
@IDE : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ : 28174043@qq.com
@GROUP: 878565760
------------------------------------
"""
from appium.webdriver import WebElement
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.support import expected_conditions as ec class Base(object): def __init__(self, driver: WebDriver):
self.driver = driver def find_element(self, locator: tuple, timeout=30) -> WebElement:
wait = WebDriverWait(self.driver, timeout)
try:
element = wait.until(lambda driver: driver.find_element(*locator))
return element
except TimeoutException as e:
print('no found element {} by {}'.format(locator[1], locator[0]))
raise e def input_value(self, locator: tuple, value):
element = self.find_element(locator)
if element:
element.clear()
return element.send_keys(value)
else:
raise NoSuchElementException("the element not found, so doesn't input value") def wait_element_presence(self, locator, timeout=30) ->WebElement:
"""等待元素出现在DOM中,但是不一定是可见的"""
wait = WebDriverWait(self.driver, timeout, 0.01)
try:
element = wait.until(ec.presence_of_element_located(locator))
return element
except TimeoutException as e:
print("the element {} not presence".format(locator[1]))
raise e def wait_element_clickable(self, locator: tuple, timeout=30):
wait = WebDriverWait(self.driver, timeout)
try:
element = wait.until(ec.element_to_be_clickable(locator))
return element
except TimeoutException as e:
print("the element {} not found or element un-clickable".format(locator[1]))
raise e def click(self, locator: tuple):
element = self.wait_element_clickable(locator)
if element:
return element.click()
else:
raise TypeError('NoneType object is not callable') def get_toast(self, context):
"""text: toast的文本值
只支持appium server 版本在1.6以上,且"automationName"为"uiautomator2"
"""
locator = (MobileBy.XPATH, "//*[@text='{}']".format(context))
toast = self.wait_element_presence(locator)
try:
try:
text = toast.text
except AttributeError:
text = toast.get_attribute("text")
except AttributeError as e:
print("get context of toast fail")
raise e
return text if __name__ == '__main__':
pass

测试代码

"""
------------------------------------
@Time : 2019/8/12 21:10
@Auth : linux超
@File : toast.py
@IDE : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ : 28174043@qq.com
@GROUP: 878565760
------------------------------------
"""
import unittest
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy from base import Base class TestToast(unittest.TestCase): phone_element = (MobileBy.ID, "com.xxzb.fenwoo:id/et_phone")
next_setup = (MobileBy.ID, "com.xxzb.fenwoo:id/btn_next_step") def setUp(self):
desired_caps = {
"automationName": "UiAutomator2",
"platformName": "Android",
"platformVersion": "5.1.1",
"deviceName": "Android Emulator",
"appPackage": "com.xxzb.fenwoo",
"appActivity": "com.xxzb.fenwoo.activity.addition.WelcomeActivity",
"noReset": "true"
}
self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps) def test_toast(self):
base = Base(self.driver)
self.driver.start_activity("com.xxzb.fenwoo", ".activity.addition.FillPhoneActivity")
base.input_value(self.phone_element, '')
base.click(self.next_setup)
toast_text = base.get_toast("无效的手机号码")
print(toast_text)
self.assertEqual("无效的手机号码", toast_text)
def tearDown(self): 
self.driver.quit() if __name__ == '__main__':
unittest.main()

封装代码中的toast方法,有一点需要说明,通过WebElement.text的方式并不一定能够获取到它的文本值,所以根据以往的经验通过get_attribute("属性")应该就能获取到了

执行过程及测试结果

如何获取app中的toast的更多相关文章

  1. 解压Assets.car获取App中的图片资源

    iOS开发时图片资源(png)是放置在Images.xcassets文件夹中进行管理的. 项目归档后就是ipa文件,在ipa文件中,Images.xcassets文件夹的内容放置在了Assets.ca ...

  2. iOS获取app图标和启动图片名字(AppIcon and LaunchImage's name)

    在某种场景下,可能我们需要获取app的图标名称和启动图片的名称.比如说app在前台时,收到了远程通知但是通知栏是不会有通知提醒的,这时我想做个模拟通知提示,需要用到icon名称:再比如在加载某个控制器 ...

  3. iOS从健康app中获取步数信息

    统计步数信息并不需要我们自己去实现,iOS自带的健康app已经为我们统计好了步数数据 我们只要使用HealthKit框架从健康app中获取这个数据信息就可以了 1.如下图所示 在Xcode中打开Hea ...

  4. iOS利用HealthKit框架从健康app中获取步数信息

    微信和QQ的每日步数最近十分火爆,我就想为自己写的项目中添加一个显示每日步数的功能,上网一搜好像并有相关的详细资料,自己动手丰衣足食. 统计步数信息并不需要我们自己去实现,iOS自带的健康app已经为 ...

  5. app中获取应用名称,版本等信息的方法

    在app中,我们有时候需要显示一些信息,例如名称,版本等等...如果用写死的方式可能不太好,我们可以动态的读取.应用的信息主要是在info.plist这个文件中,实际就是一个xml文件,以源文件的方式 ...

  6. 如需在APP中使用腾讯QQ登陆,需提前申请获取腾讯QQ的APPKEY和APPSecret。

    如需在APP中使用腾讯QQ登陆,需提前申请获取腾讯QQ的APPKEY和APPSecret. 申请流程如下: 步骤1:登陆腾讯开放平台.链接地址: http://open.qq.com/ . 步骤2:填 ...

  7. MFC中获取App,MainFrame,Doc和View类等指针的方法

    From: http://hi.baidu.com/wxnxs/item/156a68f5b3b4ed18e3e3bd03   MFC中获取App,MainFrame,Doc和View类等指针的方法 ...

  8. 小程序中关于获取app实例与当前组件

    1.getApp()来获取 App 实例 2.getCurrentPages()获取前页面栈

  9. Win 10 开发中Adaptive磁贴模板的XML文档结构,Win10 应用开发中自适应Toast通知的XML文档结构

    分享两篇Win 10应用开发的XML文档结构:Win 10 开发中Adaptive磁贴模板的XML文档结构,Win10 应用开发中自适应Toast通知的XML文档结构. Win 10 开发中Adapt ...

随机推荐

  1. windows container 踩坑记

    windows container 踩坑记 Intro 我们有一些服务是 dotnet framework 的,不能直接跑在 docker linux container 下面,最近一直在折腾把它部署 ...

  2. textarea 绕过jq验证的方法,提交空值

    <textarea placeholder=" aria-required="true" aria-describedby="OtherNotes-err ...

  3. java学习笔记(基础篇)—面向对象编程之封装、继承、多态

    一. OOP中的基本概念 Java的编程语言是面向对象的,采用这种语言进行编程称为面向对象编程(Object-Oriented Programming, OOP), 它允许设计者将面向对象设计实现为一 ...

  4. c++小游戏——扫雷

    #include<cstdio> #include<cstring> #include<algorithm> #include<conio.h> #in ...

  5. (转)android自定义控件

    原帖地址:http://my.oschina.net/wangjunhe/blog/99764 创建新的控件: 作为一个有创意的开发者,你经常会遇到安卓原生控件无法满足你的需求. 为了优化你的界面和工 ...

  6. 百度AI之百度图像识别java版本使用

    百度AI之百度图像识别java版本使用\ 官网 http://ai.baidu.com/ 创建应用 查看 appid,appkey,sk 下载sdk https://ai.baidu.com/sdk# ...

  7. Node.js实现简易的获取access_token

    还是老样子,在自学node.js的道路上走得坑坑洼洼,按住了躁动的自己,调整好心情 ,ready........Go....! 首先在项目里新建config.json,其中 appid 与 appsc ...

  8. 快速java环境变量配置记录

      配置java环境变量就是将java.exe和javac.exe的路径告诉系统,让系统能够找到这两个exe文件,废话不多说,直接开始如何配置环境变量,安装jdk时记住你的安装位置.(配置时必须要的) ...

  9. tomcat用做图片服务器

    最近做了个小网站,就是用tinyce富文本编辑器,https://www.511easy.com/ 保持字体排版和图片 发现博客园的图片,一天之后就无法显示 就想着自己做一个图片服务器,上传图片到指定 ...

  10. js - 使用jquery发送前台请求给服务器,并显示数据

    1.使用jquery发送前台请求给服务器,并显示数据 <%@ page contentType="text/html;charset=UTF-8" language=&quo ...