【问题标题】:How to test Android toast messages in Appium ( selenium Java)如何在 Appium 中测试 Android Toast 消息(selenium Java)
【发布时间】:2022-01-12 20:20:46
【问题描述】:

我正在使用 Selenium 和 Java 在 android 上运行脚本(通过 Appium 服务器)。 我发现使用 selenium 的

无法找到 toast
driver.findElement(By.LinkText("User not logged in")

在 Appium 中

但可以在 Selendroid 中用于捕获 toast 消息。

我有办法在同一个脚本中同时使用 Selendroid 和 Appium 吗?

【问题讨论】:

    标签: selenium-webdriver appium android-testing selendroid


    【解决方案1】:

    最后,我们无需截屏和执行 OCR 即可读取 toast 消息。 我已经在 Appium 1.15.1 上测试过了。

    Toast 消息位于 com.package.system 下。

    通常,用于此的 Xpath 将是“/hierarchy/android.widget.Toast”。 而且,类名将是“android.widget.settings”

    您可以通过在显示 toast 消息时刷新元素检查器屏幕来确认这一点。

    WebDriverWait waitForToast = new WebDriverWait(driver.25);
    
    waitForToast.until(ExpectedConditions.presenceOfElementLoacted(By.xpath("/hierarchy/android.widget.Toast")));
    
    String toastMessage = driver.findElement((By.xpath("/hierarchy/android.widget.Toast")).getText();
    
    System.out.println(toastMessage);
    

    【讨论】:

    • 是的,我认为这是最简单的解决方案。尝试使用 Appium 1.17.1 - 有效。但有一件事,visibilityOfElementLocated 不适用于 toast 通知。如上例所示,必须使用presenceOfElementLoacted
    • 是的,与 OCR 方法(屏幕截图方法)相比,此方法节省了大量时间。
    • 虽然这不适用于 appium 检查器,对吗?,我无法使用 1.20 版检查器选择 android toast 消息
    • 尝试扩展xml层次结构看看。 Toast 消息通常会结束层次结构。我还没有使用1.20。它在 1.15 检查器上运行良好。
    【解决方案2】:

    方法一: Appium 1.6.4 版本支持 toast 消息,为此您需要使用automationName:'uiautomator2'

    toast = driver.find_element(:xpath, "//android.widget.Toast[1]")
    if toast.text == "Hello" 
    

    但我不建议这样做,因为 uiautomator2 还不稳定。

    方法二:

    1. 在屏幕上触发短信
    2. 截屏
    3. 将图像转换为文本文件

      def assettoast(string)
        sname = (0...8).map { (65 + rand(26)).chr }.join
        $driver.driver.save_screenshot("#{sname}")
      
        # Make sure tesseract is installed in the system. If not you can install using "brew install tesseract" in mac
        system ("tesseract #{sname} #{sname}")
      
        text_file="#{sname}.txt"
        var= get_string_from_file(string, text_file)
        raise if var != true
      end
      
    4. 检查文本文件中是否有toast消息

      def get_string_from_file(word, filename)
        File.readlines(filename).each do |line|
        return true if line.include?(word)
        end
      end
      

    【讨论】:

      【解决方案3】:

      您似乎无法在同一会话中切换驱动程序类型。 如果您尝试切换到 Selendroid 仅用于 Toast 验证 - 您可以使用 OSR 图像识别引擎。

      查看这个答案w/ Ruby bindings

      想法很简单:

      • 让 toast 消息出现
      • 截几张截图
      • 遍历截取的屏幕截图并查找所需的文本

      以下是 Java 中 OCR 使用的简单示例:tess4j example(确保已安装 Tesseract 引擎)

      【讨论】:

      • 谢谢!!所以我从tess4j.sourceforge.net 下载了 Tess4J 2.0,我在 Eclipse 中将所有 jar 文件添加到我的项目中,我还给出了以下命令,将 dll 文件 gsdll32、libtesseract303 和 liblept170 包含在代码 System.setProperty 中的文件夹 dllfiles 中( "jna.library.path","C:\\Tess4J\\dllfiles); 运行示例代码时抛出错误“线程“main”中的异常 java.lang.UnsatisfiedLinkError: 找不到指定的模块"
      • 我能够解决该错误。该代码使用了不起作用的 doOCR 函数。造成此错误的是 Microsoft VC++。我安装了 VC++ 2013 并运行了代码,但现在问题是 tesseract 没有正确转换图像。它缺少很多文本,并且它识别的一些文本是不正确的。我可以使用其他任何好的 OCR 吗?
      • @RJX 实际上,您应该首先使用图像以使其“可读”img.contrast.normalize.negate.posterize(3).adaptive_resize(3) 如您所见,我使用 ImageMagick 来对比、规范化、否定、分离和调整它的大小 x3。这就是我发现在我的项目中运作良好的原因
      【解决方案4】:
      Step 1:
      File scrFile=null;
      String path1 = null;
      BufferedImage originalImage=null;
      BufferedImage resizedImage=null;
      System.out.println("Starting\n\n\n\n");
      scrFile = ((TakesScreenshot) appiumDriver).getScreenshotAs(OutputType.FILE);
      System.out.println("after scrfile\n\n\n\n");
      originalImage = ImageIO.read(scrFile);
      System.out.println("after originalFile\n\n\n");
      BufferedImage.TYPE_INT_ARGB : originalImage.getType();
      resizedImage = CommonUtilities.resizeImage(originalImage, IMG_HEIGHT, IMG_WIDTH);
      ImageIO.write(resizedImage, "jpg", new File(path + "/"+ testCaseId + "/img/" + index + ".jpg"));
      Image jpeg = Image.getInstance(path + "/" + testCaseId + "/img/"+ index + ".jpg");
      Step 2: 
      BufferedImage pathforToast= original image;
      Step 3:
      System.setProperty("jna.library.path","C:/Users/Dell/workspace/MOBILEFRAMEWORK/dlls/x64/");
      Tesseract instance = Tesseract.getInstance();
      `enter code here`ImageIO.scanForPlugins();
      String result=null;
      result = instance.doOCR(pathforToast);`enter code here`
      System.out.println(result);`enter code here`
      

      【讨论】:

        【解决方案5】:

        Appium 1.6.4@beta 最新版本支持 toast 消息

        【讨论】:

          【解决方案6】:

          截取 Toast Message 页面的屏幕截图并尝试将图像文件转换为文本并使用以下代码验证文本。

            public void imageconversion(String filePath) throws IOException,          
              {    
                          ITesseract instance = new Tesseract();
              //file path is the image which you need to convert to text
                          File imageFile = new File(filePath);  
                          BufferedImage img = null;
                          img = ImageIO.read(imageFile);
                          BufferedImage blackNWhite = new BufferedImage(img.getWidth(),img.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
                          Graphics2D graphics = blackNWhite.createGraphics();
                          graphics.drawImage(img, 0, 0, null);
                          //path where your downloaded tessdata exists
                          instance.setDatapath("E://ocr//data"); 
                        //What language you required to convert,( e.g. English)
                          instance.setLanguage("eng");        
                          String result = instance.doOCR(blackNWhite);
          
          
                          System.out.println(result);
          
                      }
          

          【讨论】:

            【解决方案7】:

            Appium 直接不提供任何 API 来读取我们需要使用 tess4j jar 来读取 toast 消息。首先我们需要拍摄屏幕截图,然后我们需要使用 tess4j API 从屏幕截图中读取文本。

             static String scrShotDir = "screenshots";
              File scrFile;
              static File scrShotDirPath = new java.io.File("./"+ scrShotDir+ "//");
              String destFile;
              static AndroidDriver driver = null;
            
             public String readToastMessage() throws TesseractException {
            String imgName = takeScreenShot();
              String result = null;
              File imageFile = new File(scrShotDirPath, imgName);
              System.out.println("Image name is :" + imageFile.toString());
              ITesseract instance = new Tesseract();
            
              File tessDataFolder = LoadLibs.extractTessResources("tessdata"); // Extracts
                               // Tessdata
                               // folder
                               // from
                               // referenced
                               // tess4j
                               // jar
                               // for
                               // language
                               // support
              instance.setDatapath(tessDataFolder.getAbsolutePath()); // sets tessData
                            // path
            
              result = instance.doOCR(imageFile);
              System.out.println(result);
              return result;
             }
            
             /**
              * Takes screenshot of active screen
              * 
              * @return ImageFileName
              */
             public String takeScreenShot() {
              File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); 
            
              SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy__hh_mm_ssaa");
              new File(scrShotDir).mkdirs(); // Create folder under project with name
                      // "screenshots" if doesn't exist
              destFile = dateFormat.format(new Date()) + ".png"; // Set file name
                           // using current
                           // date time.
              try {
               FileUtils.copyFile(scrFile, new File(scrShotDir + "/" + destFile)); // Copy
                                // paste
                                // file
                                // at
                                // destination
                                // folder
                                // location
              } catch (IOException e) {
               System.out.println("Image not transfered to screenshot folder");
               e.printStackTrace();
              }
              return destFile;
             }
            

            欲了解更多详情,请参阅此视频 - https://www.youtube.com/watch?v=lM6-ZFXiSls

            【讨论】:

              【解决方案8】:

              我找到了三种方法来捕获 Toast 消息并进行验证。

              1. 获取页面源并从中验证 toast 消息。

              
              
              

              public void verifyToastMessageUsingPageSource(String toastmsg) throws InterruptedException { boolean found = false; for(int i =0 ; i <8; i++){ if(getDriver().getPageSource().contains("class=\"android.widget.Toast\" text=\""+toastmsg+"\"")){ found = true; break; } Thread.sleep(300); } Assert.assertTrue(found,"toast message "+toastmsg+" is present"); }

              可以使用Xpath: //android.widget.Toast[1]找到类似的

              1. 使用 grep 命令,在 uiautomator 事件中等待 toast 消息。 在点击之前运行命令,toast 消息将被修改。

                adb shell uiautomator 事件 | grep "ToastMessgae"

              2. 这很棘手,需要更多代码才能运行。

                • 开始捕获屏幕截图线程。
                • 执行点击操作
                • 停止屏幕捕获线程。
                • 使用 OCR 从捕获的图像中提取文本,并验证 Toast 消息是否存在于捕获的图像中。

              我更喜欢第一个和第二个选项,它可以用更少的代码在更短的时间内提供验证。

              如果您需要第 2 点和第 3 点的代码,请发表评论。

              【讨论】:

                【解决方案9】:

                Appium 版本号>=1.6.4 支持 UiAutomator2 的 toast 通知。 在带有 webdriver 的 Javascript 中,您可以这样做

                let toast=await driver1.elements("xpath","/hierarchy/android.widget.Toast");
                let data=await toast[0].text();
                console.log(data)

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-01-25
                  • 1970-01-01
                  • 2020-06-16
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-07-15
                  • 1970-01-01
                  相关资源
                  最近更新 更多