页面元素无法获取到的场景
Ex:bilibili的登录页面
登录页面做了截图限制,不能通过外部的工具(如appium检查器,adb命令)进行截图,像一些银行类的app某些页面也可能会做限制不让截图
问题:如何知道页面是否做了截图限制
(1)appium检查器如果能打开,则没有做限制,打不开就做了限制
image.png
(2)通过adb截图,如下命令,截取当前正在运行的页面保存到手机/sdcard/目录下,如果手机/sdcard/目录下有此登录页的截图,说明没有做限制,如果没有截图,则做了限制
adb shell screencap -p /sdcard/aaa.png
既然页面做了截图限制,无法用外部工具获取元素的定位信息,那么怎么解决呢?
解决方案:使用getPageSource API来获取页面的定位信息即:获取当前页面的源代码,然后在源代码中查找是否有页面的元素定位信息,如下图是获取的源代码,红色部分就是要定位的元素
image.png
代码如下:
package com.leom.day03;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import io.appium.java_client.android.AndroidDriver;
public class SpecialLocate {
public AndroidDriver androidDriver;
/**
* 初始化的一些操做就相等于是appium的检测器会话, 即:不通过检查器会话连接手机,而是通过代码代替客户端来连接手机设备
*/
@BeforeTest
public void setup() throws MalformedURLException {
// 1.实例化 DesiredCapabilities--》所需能力
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
// 2.添加手机配置
desiredCapabilities.setCapability("deviceName", "127.0.0.1:62001");// 设备名(值可以自己定义)
desiredCapabilities.setCapability("platformName", "Android");// 连接的设备是安卓平台
desiredCapabilities.setCapability("appPackage", "tv.danmaku.bili");// app包名
desiredCapabilities.setCapability("appActivity", "tv.danmaku.bili.ui.splash.SplashActivity");// app启动入口
desiredCapabilities.setCapability("noReset", "true");
// 3.Appium服务连接地址
URL url = new URL("http://127.0.0.1:4723/wd/hub");
// 4.实例化AndroidDriver
androidDriver = new AndroidDriver(url, desiredCapabilities);
// 5.设置隐式等待
androidDriver.manage().timeouts().implicitlyWait(8, TimeUnit.SECONDS);
}
@Test
public void test() throws InterruptedException {
androidDriver.findElement(By.id("tv.danmaku.bili:id/drawer_handler")).click();
androidDriver.findElement(By.id("tv.danmaku.bili:id/login")).click();
Thread.sleep(8000);// 等待的时间设置长一点,app加载的有点慢
//辅助的功能-》用来获取页面元素信息
// System.out.println( androidDriver.getPageSource());
androidDriver.findElement(By.id("tv.danmaku.bili:id/et_phone_number")).sendKeys("13323234545");
}
}
Toast元素获取
》提示信息,出现的时机是没有规律的(与响应时间和网络有关系),出现之后过几秒就会消失--》可以用来做断言
获取要求:(1)手机系统版本5.0或者以上(2) Appium设置uiautomator2引擎(Appium默认就是uiautomator2引擎)
xpath表达式获取://*[contains(@text,'错误的账号信息)]
@Test
public void test() throws InterruptedException {
// 登录
androidDriver.findElement(By.id("com.lemon.lemonban:id/navigation_tiku")).click();
androidDriver.findElement(By.id("com.lemon.lemonban:id/button_go_login")).click();
androidDriver.findElement(By.id("com.lemon.lemonban:id/et_mobile")).sendKeys("13323234545");
androidDriver.findElement(By.id("com.lemon.lemonban:id/et_password")).sendKeys("12345678");
androidDriver.findElement(By.id("com.lemon.lemonban:id/btn_login")).click();
// 获取toast信息
// appium点击登录截取不到toast的,只有模拟器点击登录,appium再刷新,才能再appium中看到toast信息
// 且:通过选择元素,toast也是选择不了的,但是toast却是存在当前页面中,=》对于这种特殊元素定位方式
// 采用xpath:这里的text是元素的属性,*代表任意标签
WebElement element = androidDriver.findElement(By.xpath("//*[contains(@text,'错误的账号信息')]"));
//打印出toast文本
System.out.println(element.getText());
}
滑动列表元素-》页面元素需要像上滑动才可以看见的元素
定位方式:根据文本定位
需要滑动几次?->有些元素不需要滑动,有些元素需要滑动多次才可以加载出来-》解决方式:循环滑动
什么时候结束滑动呢?(1)滑动到了底部,还没有找到元素,就跳出循环 (2)默认页面已加载出来元素,不需要滑动时,也跳出循环
如何判断是否滑动到了底部呢?-》滑动到了底部,页面不能继续向上滑动了,所以可以根据pageSource判断,当滑动前和滑动后pageSource相等,说明滑动到了底部
代码如下:
/**
* 滑动列表元素定位
*/
@Test
public void test02() {
// 1 点击 题库
androidDriver.findElement(By.id("com.lemon.lemonban:id/navigation_tiku")).click();
// 2.通过文本定位-》比如这里 我们要定位 “ 逻辑思维题"
// androidDriver.findElementByAndroidUIAutomator("new
// UiSelector().text(\"逻辑思维题 \")").click();
slide("软件测试基础");
}
public void slide(String text) {
String BeforepageSource = "";
String AfterpageSource = " ";
// 条件:什么时候结束滑动?
// 1.到了底部还是找不到元素,就跳出循环
// 2.默认的页面就有元素,不需要滑动,也跳出循环
while (true) {
// 滑动前的pageSource
BeforepageSource = androidDriver.getPageSource();
if (BeforepageSource.contains(text )) {
//注意:\"" -》不能写成 \" " 不能加空格,否则会找不到元素,相当于元素文本有空格
androidDriver.findElementByAndroidUIAutomator("new UiSelector().text(\"" + text + "\")")
.click();
break;
}
// 向上滑动
swipeUp();
// 滑动后的pageSource
AfterpageSource = androidDriver.getPageSource();
if (BeforepageSource.equals(AfterpageSource)) {
break;
}
}
}
/**向上滑动
*
*/
public void swipeUp() {
int height = androidDriver.manage().window().getSize().getHeight();
int width = androidDriver.manage().window().getSize().getWidth();
int startx = width / 2;
int starty = height * 3 / 4;
int endx = width / 2;
int endy = height / 4;
int duration = 500;
// 1.实例化触摸动作对象
TouchAction touchAction = new TouchAction(androidDriver);
// 2.将原始坐标转化成PointOption类型(java client高版本不能直接传坐标值)
PointOption startPoint = PointOption.point(startx, starty);
PointOption endPoint = PointOption.point(endx, endy);
// 3.把原始时间转换成WaitOptions类型的(原始时间是毫秒,所以调用ofMillis()
Duration duration2 = Duration.ofMillis(duration);
WaitOptions waitOptions = WaitOptions.waitOptions(duration2);
// 4.配置滑动的动作
touchAction.press(startPoint).waitAction(waitOptions).moveTo(endPoint).release();
// 5.让滑动生效
touchAction.perform();
}
网友评论