Appium 自动测试,读书打卡(日志)

1.准备工作

1.1了解Appium 自动测试

   Appium 官方链接:https://appium.io/docs/en/about-appium/intro/。 

1.2软件安装

  1.JDK

  2.Android SDK 

      下载链接:https://www.androiddevtools.cn/

      在配置环境变量时,遇到以下问题。

    (1)在配置Android SDK 环境时,发现没有找到adb.exe文件,后来查找资料,发现是没有platforms-tools。如下图所示。

               

      (2)上网搜索可能原因,有人说可能是platform-tools在安装时被误删,打开 Android SDK Manager看看platform-tools是否被误删,发现果然被误删了。

             

       (3)安装platform-tools。

           

     (4)配置环境变量。

         

     (5)配置系统环境变量。

           

       (6)在命令行测试Android SDK 环境安装成功。

           

参考博客链接:https://www.csdn.net/tags/MtjaggzsNTc4MjktYmxvZwO0O0OO0O0O.html。

  3.Appium 

     下载链接:https://github.com/appium/appium-desktop/releases/download/v1.22.3/Appium.Server.GUI-windows-1.22.3.exe

      下载完成后操作

  (1)双击Appium进行安装,安装完成后,出现以下界面。将Host设置为127.0.0.1,Port设置为4723,如果没有配置JDK或者ANDROID_HOME环境变量,需要点击“Edit Configurations”处。

             

 

         (2)如果忘记了是否配置了环境,可以点击“Edit Configurations”进行查看,由于我是环境都配置完成了,所以这里会自动填写上。

             

         (3)开启服务,进入到服务界面。看到欢迎你,Appium的客户端就算完成了。

           

  4.夜神模拟器

     下载链接:https://www.yeshen.com/

1.2说明

      本项目只用于技术讨论。

2.需求分析

       手机上的读书软件,自动完成读书并打卡。这里需要先找到读书软件,然后点击读书软件,在读书软件中找到需要阅读的书籍,点击需要阅读的书籍,每隔固定时间滑动屏幕进行翻页,设置固定阅读总时长,到达总时长后,结束阅读。在当前页面中找到页码和总页码,读出来这两个量。进行读书打卡。

3.技术原型

  1.appium读app

  2.appium点击屏幕

  3.appium滑动屏幕

  4.识别固定位置上的数字

4.实验

4.1Appium连接安卓模拟器

4.1.1实验目的

了解Appium是如何和安卓模拟器连接的。

4.1.2实验内容

4.1.2.1准备工作

1.进入模拟器中的设置,找到安卓版本号位置,多次点击。进入开发者模式。

 2.多次点击后,会提示进入到开发者模式。

 3.查看Android SDK的adb版本。

4.进入模拟器bin目录下,执行nox_adb.exe version,查看adb版本。发现两者的版本不一致。如果版本不一致,需要把Android SDK下的adb版本复制到模拟器bin目录下。并把Android SDK下的adb重新命名为nox_adb。

 5.当把Android SDK下的adb重新命名为nox_adb后,复制到模拟器bin目录下后,访问被拒绝。

 

 6.然后我把原来模拟器bin目录下nox_adb.exe删除。就能复制过去。

 7.再次查看模拟器下的adb版本,发现和Android SDK下的adb版本版本一致。

 

 8.连接模拟器,发现无法连接。

 

解决无法连接问题。

参考链接: https://blog.csdn.net/DaisyCold/article/details/111477842 。

(1)查看别人博客显示我少复制了两个文件。把Android SDK安装目录下画红框位置的两个文件也复制到模拟器bin目录下。

(2)在模拟器bin目录下替换复制过来的文件。

 

 (3)再次查看adb版本,发现两个版本一致了。

 

 (4)再次连接,连接成功。

 

4.1.2.2创建Maven项目

1.点击file下创建新的Maven项目。

 2.选择创建一个简单的工程。

 

 3.填写信息。

 

 4点击完成后报错。显示无效的工程描述,信息如下。

 

 

 

5.查找原因,说创建Maven时不能选择新的工作空间,需要选择默认的工作空间。选择默认的工作空间后,创建成功。

 

4.2.1.3安装Maven

1.下载链接:https://maven.apache.org/download.cgi 。

 2.配置环境变量。

 

 

 参考链接:https://www.runoob.com/maven/maven-setup.html

 3.测试maven环境是否配置成功,输入mvn -version,显示版本信息,表示配置成功。

4.1.2.4Maven安装Java-client

Java-client连接:https://mvnrepository.com/ 。

1.打开Maven Repository,搜素Appium。找到Java Client。

 2.点击Java Client,复制依赖。

 3.在项目中的pom.xml文件中复制依赖。

4.eclipase配置Maven。如下图所示。找到eclipse中Windown下的preferences,第一步在Maven下找到Installations并点击,第二步点击Add,第三步选择Maven的安装路径。

 

 5.编写测试代码。

import org.openqa.selenium.remote.DesiredCapabilities;

import io.appium.java_client.android.AndroidDriver;

public class TestApp1 {
    public static void main(String[] args) throws MalformedURLException, InterruptedException {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        // 模拟器类型
//        capabilities.setCapability("deviceName", "Android Emulator");
        capabilities.setCapability("deviceName", "device");
        // 自动化测试引擎
        capabilities.setCapability("automationName", "Appium");
        // 手机操作系统Android
        capabilities.setCapability("platformName", "Android");
        // 手机操作系统版本号
        capabilities.setCapability("platformVersion", "7.1.2");
        // app包名
        capabilities.setCapability("appPackage", "com.android.settings");
        // app中启动的Activity名称
        capabilities.setCapability("appActivity", ".Settings");

        AndroidDriver driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);

        driver.quit();
    }
}

4.1.2.5解决程序错误

使用代码测试能否启动模拟器中的设置,目前报错信息如下。

4.1.2.5.1问题一

1.猜测是代码中的包名或者其他信息填写错误,检查一遍代码,排查了这个可能性。然后又针对报错信息,一条一条的看。先解决第一个问题。

 

 2.查找原因,网上好多说是需要添加依赖,然后就添加了以下的依赖。参考链接:https://blog.csdn.net/zhizhengguan/article/details/103312010 。

4.1.2.5.2问题二

1.解决完问题一后,下面解决问题二。如下图所示。

 2.寻找解决办法,跟着添加了一堆依赖,也还是报错。

<!--  错误依赖-->
<!--  <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>3.141.59</version>
    </dependency> 
    <dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>22.0</version>
</dependency> -->

 3.不知道该怎么办了,就查看了Appium,发现这里也有一些信息,而且有以下几个问题,好像是缺少一些东西。

 

 4.我其实并不知道缺少的是什么,我在我电脑上搜索是否真的没有这个文件。然后就发现有这个文件。

 

 5.我以为是目录不对,按照提示的目录找了一下,还是存在缺少的apk。到这里我卡主了,我不知道问题出在了哪里。

 

 6.然后我又看了一下是否还存在其他问题,解决又找到了新的问题。

 

7.通过查看别人解决方案,发现build-tools/目录下应该有“apksigner.jar”文件但是我电脑上没有。

8.我上网想下个“apksigner.jar”,但是我找了半天不是找不到,就是要花钱,所以我放弃这个想法了。

9.然后我看到一个博客中的解决方法,里面是复制build-tools下的apksigner.jar,我记得昨天android SDK里面缺少东西时,在SDK Manager.exe中安装过platform-tools。

 

10.然后我想着在SDK Manager.exe中是不是也可以找到build-tools,打开SDK Manager.exe后,真的找到了,然后下载。

4.1.2.5实验结果

运行java程序,打开了设置。

 

4.2 Appium点击出现的代码问题

1.在调试代码时,这里出现了报错。这里是不支持这两个参数。

 

 2.查找资料,需要把坐标以point对象的形式放到Tap方法中才可以。

 

 

参考链接:https://blog.csdn.net/hccgk/article/details/103169057/ 。

 

4.3 Appium滑动出现的代码问题

1.想使用swipe方法实现互动效果,但是编写以下代码,然后报错,如下图

 

 

 2.看来swipe已经不能使用了。

4.4 Appium定位元素出现的问题

1.使用Appium Inspector获取设置中WLAN选项的ID时,出现以下问题,没有找到WLAN选项的ID,只能找到WLAN选项的xpath,如下图所示。

2.在查阅了一些资料说resource-id是选择元素的ID,但是经过我的实验,其他的元素也是这个ID。比如蓝牙的ID。

 

 

 3.又对比了其他元素的其他属性,发现只有Text属性不一样。

4.查找原因,是因为上面是查看的布局ID。需要查看选择中标签的ID。

 

 5.写完正确ID后,编写代码,报没有findElementById()的方法,尝试了其他的定位属性,也没有。

 6.上网搜索好久也没有找到解决办法,猜测是不是版本的问题。然后降低版本。降低版本后AndroidDriver又不兼容。

 

7.把java-client改成7.6.0版本。

 8.报以下的错误,不能创建远程会话。

 9.查看日志。发现以下三处问题。

 

 

 10.搜索原因,看到有一个说降低Appium版本。我尝试降低了Appium版本。结果真的好了。

4.5 Appium识别元素出现的问题

1.网上搜索资料,一开始找到的是使用getText()方法,但是我在获取WLAN的值时获取不到。

2.我尝试了其他几种获取属性值的方法,发现只有getAttribute(“className”)方法可以获取到值。

3.又查找资料,看到有一个获取界面资源代码的方法,可以获取到界面的代码。

driver.getPageSource()//获取到界面代码

4.实在找不到啥方法可以获取到属性值的方法,我想了一下界面代码都有了,要是我按照id先找到所需属性所在行,然后再取出所需值就可以。按照以下代码,把界面代码按行分割,然后在每行中匹配所需id。

String resource_origin = driver.getPageSource();//获取到界面代码
        String[] resources = resource_origin.split("\n");
        for (String str : resources) {
            int intIndex = str.indexOf(wifi_id);
            if (intIndex != -1) {
                System.out.println("找到:  " + str);
            }

        }

5.先找到所需代码所在行,运行程序看一下效果,才发现,原来这个id不是唯一的,同时也明白了为啥一开始使用getText()获取不到值的。因为ID不唯一,而第一个匹配上的ID中的内容就是空,所以一直获取不到。

6.怀疑其他软件的ID唯一,打开微信读书,查看ID,发现ID是唯一的。

7.后来使用微信读书获取所需ID的文本内容。

5.实现

5.1出现的问题

1.微信读书中没有ID,选用了xpath来找到书籍。

 

 

2.微信读书获取不了页码,点击页码时,会全选,不能单独选择页码,也就获取不了ID或者xpath。

3. 获取界面代码,查看页面是以什么形式存在界面中的。

4.查看页面代码,没有发现里面包含页码信息。

 5.再找了一圈之后,我发现这可能是一张图片,但是又不像图片。然后我放弃了使用属性获取内容,打算换技术路线,使用图片识别技术。

 5.2获取页码思路

使用图片识别图中文字,需要经过以下两个步骤,第一步图片分割。第二步识别图中的文字。

5.2.1识别图片问题

5.2.1.1使用百度API

1.添加以下代码的依赖。

      <dependency>
            <groupId>com.baidu.aip</groupId>
            <artifactId>java-sdk</artifactId>
            <version>4.8.0</version>
       </dependency>

2.注册登录百度智能云,创建一个应用,创建完需要等待三十分钟。

 

 3.复制以下代码。(未完成,因为有的包不能导入,然后放弃了这个方法)

/**
 * @describe 识别图片上的文字
 * 官方文档:https://ai.baidu.com/ai-doc/OCR/Ikibizxql
 */
public class Word {
    // 设置APPID/AK/SK
    public static final String appId = "你的 App ID";
    public static final String apiKey = "你的 Api Key";
    public static final String secretKey = "你的 Api Key";
    public static final AipOcr client = new AipOcr(appId, apiKey, secretKey);
 
    /*
     * 文字识别方法
     */
    public static String imgOcr(String imgpath)
    {
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("language_type", "CHN_ENG");
        options.put("detect_direction", "true");
        options.put("detect_language", "true");
        options.put("probability", "true");
        // 参数为本地路径
        JSONObject res = client.basicGeneral(imgpath, options);
        //解析json
        JSONArray wordsResult = (JSONArray)res.get("words_result");
        String ocrStr = "\n";
        StringBuffer sb=new StringBuffer();
        for(Object obj : wordsResult)
        {
            JSONObject jo = (JSONObject)obj;
            sb.append(jo.getString("words") + "\n");
        }
        return sb.toString();
    }
 
    public static void main(String[] args) throws AWTException, IOException {
        String s = StartApp.imgOcr("C:\\Users\\Administrator\\Desktop\\sw_image\\a.png");
        System.out.println(s);
    }

 

5.2.1.2使用软件包识别图片文字

1.运行程序后,出现以下界面。

 

2.配置环境变量后,在命令行中输入tesseract后,出现以下信息则代表环境变量配置完成。

 

 3.运行程序后,还是报原来的错误。这里找了好久问题。又重新安装了Tesseract-OCR 。

 4.最终发现了问题。这里有两个原因导致的报错,一是安装目录中不能有非法字符(在我第一次安装时,安装路径中多了空格)。二是在安装时,没有安装语言包(第一次安装时没有勾选语言包),导致识别不了。

 

 5.2完善项目问题

5.2.1设定每页读书间隔

1.在确定需要设置两个固定时间后,先设置每页阅读40s,先尝试阅读120s,但是运行程序时,发现没有获取到页码,一开始以为机器没有睡醒,多运行几次还是这样。然后找到截图,发现截图也不正确。如下图所示。后来一直摁撤回,还原到昨晚好使的代码,但是运行程序还是获取不到页码,截图还是下面截图。

2.想着可能是模拟器有问题,重新打开模拟器,再次运行程序,发现读书界面也没有打开(就像网不好,一直显示加载)。后来又运行了几次,可以打开微信读书了,但是截图还是上门的截图。

3.我感觉我代码被猫吃了,吓的我把电脑关机重启,所有软件都关闭重新打开。

4.我猜测是网络不好,换成手机的网络,运行程序后,还是上面截图的效果。

5.我把网络关闭,运行程序,也能打开模拟器,并且截图是上面的截图。

6.我不知道这是什么原因导致的,我又猜测是模拟器坏了,卸载模拟器,重新安装,运行程序,但是不能创建一个新的远程会话。

 

 

 7.查看是否是两个版本的adb不一致。果然是两个版本不一致,但是我已经把Android SDK下的adb版本复制到模拟器bin目录下啊。

 

 8.我感觉可能是自己脑子坏了,再重新替换一下。再次查看版本,这次版本一致了。

 

9.运行程序报错。 

 

 10.在命令行查看是否连接。

 

 11.启动Appium,运行程序。发现截图还是花的图片。

12.排除了是模拟器的原因,难道是因为微信读书还没有结束就开始截图吗,但是程序执行不应该是从上到下嘛?设定的是先滑动界面,等到一段时间然后再截图啊,而且昨天为啥好好的啊,这里也没有牵扯网络异步啊。

13.我突然又想到是不是真的是等待时间的问题,抛开项目,只打开微信,查看截图是否会改变。

14.发现截图这次真的变了,而且裁剪图片效果也是对的。所以问题可能真的出在等待时间上。

14.上网搜索“appium等待页面渲染完成执行方法”,发现有三种等待方式,都试了一下,发现生成的图片还是错误的图片。而在每次查看截图时,突然发现了以下的效果,从截图中可以看出,当前页面的文字应该是被截到了,但是却多了书架界面,两个界面重合在一起了。

 15.修改noReset,本来想修改成false,目的是测试截图是否正确,却发现设置成true时,没有加双引号,加上双引号后,运行程序,程序可以正确截图并获取页码了。

 16.然后把滑动代码加上后,截图还是显示的两个图片的混合。所以这里猜测是或许是滑动和截图在时间上冲突了。

 

 17.把等待时间加大,并且添加以下等待渲染需要阅读的内容,运行程序,查看效果。

//    等待元素出现
    public static void waitElement(final AndroidDriver driver) {
//        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        WebDriverWait web = new WebDriverWait(driver, 10);
        WebElement webElement = web.until(new ExpectedCondition<WebElement>() {
            public WebElement apply(WebDriver input) {
                return driver.findElementByXPath(
                        "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout\r\n");
            }
        });
//        webElement.click();
    }

18.在多次运行中,有时截图是正确的,能获取到页码,但是有时就不能获取到正确截图。

19到目前位置,做不下去了。

5.2.2获取正确截图

1.等待足够长的时间后,再截图,但是发现截图后的效果还是花的图片。

2.使用Thread.sleep()来阻塞页面,等滑动完微信读书后才开始截图。但是运行的效果是个1中一样的效果。

3.使用回调函数。运行程序后,还是和1中一样的效果。

    public static void waitElement(final AndroidDriver driver) {
//        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        WebDriverWait web = new WebDriverWait(driver, 10);
        WebElement webElement = web.until(new ExpectedCondition<WebElement>() {
            public WebElement apply(WebDriver input) {
                return driver.findElementByXPath(
                        "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout\r\n");
            }
        });
//        webElement.click();
    }

 4.后来,我把滑动页面的方法去掉,查看截图是否正常。运行程序后发现截图是正常的,但是添加上滑动代码,截图就不正确了。我实在搞不明白这是为啥。添加滑动界面代码生成的图如下图左边第一张和第二张所示,去掉滑动界面代码生成的图如下图左边第三张和第四张所示。

 5.我猜测这个原因可能已经和时间没有关系,或许是别的原因啥的,但是我也不知道啥原因。

 

5.2.3微信打卡

1.当获取到页码后,需要把页码发到微信固定的群里,然后自动实现打卡,但是在打卡时,程序一直运行报错。

 

 2.这里发现是因为微信读书和微信的包名还有启动页acitivity 不一样,即微信和微信读书的这两个参数是不一样的。

 3.获取微信driver单独写一个方法。

//    获取微信driver
    public static AndroidDriver getWechatDriver() throws Exception {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        // 模拟器类型
        // capabilities.setCapability("deviceName", "Android Emulator");
        capabilities.setCapability("deviceName", "device");
        // 自动化测试引擎
        capabilities.setCapability("automationName", "Appium");
        // 手机操作系统Android
        capabilities.setCapability("platformName", "Android");
        // 手机操作系统版本号
        capabilities.setCapability("platformVersion", "7.1.2");
        // app包名
        capabilities.setCapability("appPackage", "com.tencent.mm");
        // app中启动的 Activity名称
        capabilities.setCapability("appActivity", ".ui.LauncherUI");
        capabilities.setCapability("automationName", "uiautomator2");
        // noReset设置
        capabilities.setCapability("noReset", "true");
        // 设置appium可以输入中文
        capabilities.setCapability("unicodeKeyboard", "true");
        AndroidDriver driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
        return driver;
    }

 

6.PSP

 

 

 

 

 

posted @ 2022-04-17 14:30  萍2樱释  阅读(210)  评论(0编辑  收藏  举报