我使用Java Selenium在android上运行脚本(通过Appium服务器)。我发现用selenium的
来定位toast是不可能的。driver.findElement(By.LinkText("User not logged in")
在Appium 但是可以在selendoid中用于捕获吐司消息。
我有一种方法,我可以使用selendoid和Appium在同一脚本?
最后,我们能够在不需要截图和执行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);
方法1:来自Appium 1.6.4版本支持toast消息,为此您需要使用automationName:'uiautomator2'
。
toast = driver.find_element(:xpath, "//android.widget.Toast[1]")
if toast.text == "Hello"
但我不建议这样做,因为uiautomator2还不稳定。
方法2:- 触发屏幕文本信息
- 捕捉截图
将图像转换为文本文件
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
检查文本文件中是否有toast message
def get_string_from_file(word, filename) File.readlines(filename).each do |line| return true if line.include?(word) end end
看起来您不能在同一会话中切换驱动程序类型。如果你想切换到Selendroid只是为了吐司验证-你可以使用OSR图像识别引擎。
检查这个答案w/Ruby bindings
想法很简单:
- 使祝酒词出现
- 少截图
- 遍历截图并寻找所需的文本
Step 1:
File scrFile=null;
String path1 = null;
BufferedImage originalImage=null;
BufferedImage resizedImage=null;
System.out.println("Startingnnnn");
scrFile = ((TakesScreenshot) appiumDriver).getScreenshotAs(OutputType.FILE);
System.out.println("after scrfilennnn");
originalImage = ImageIO.read(scrFile);
System.out.println("after originalFilennn");
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`
Appium 1.6.4@beta最新版本支持toast消息
截取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);
}
Appium直接没有提供任何API来读取toast消息,我们需要使用tess4j jar来完成它。首先,我们需要截取屏幕截图,然后我们需要使用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
我找到了捕获Toast消息并验证它们的三种方法。
- 获取页面源并从中验证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");
}
Similar can be found using Xpath: //android.widget.Toast[1]
Using the grep command, wait for a toast message in uiautomator events. run the command before clicking and toast message will be varified.
adb shell uiautomator events | grep "ToastMessgae"
This is tricky and needs more code to run.
- start capturing screenshots thread.
- perform click action
- stop screen capturing thread.
- extract text from the captured images using OCR and verify the toast message is present in the captured images.
I prefer the 1st and 2nd option, it provides validation in less time with less code.
comment if you need code for 2nd and 3rd point.
Appium with version number>=1.6.4 supports toast notification with UiAutomator2. In Javascript with webdriver you can do like this
let toast=await driver1.elements("xpath","/hierarchy/android.widget.Toast");
let data=await toast[0].text();
console.log(data)
Appium + Javascript解决方案
在helper类中创建一个函数,并在测试文件中使用实际文本参数
调用它Helperclass.js
-----------------------------
async isToastMessageDisplayed(toastText) {
const numberOfAttempts = 2; // Adjust the number of attempts as needed
const waitTime = 200; // Adjust the wait time between attempts in milliseconds
for (let i = 0; i < numberOfAttempts; i++) {
await driver.pause(waitTime);
const pageSource = await driver.getPageSource();
if (pageSource.includes(toastText)) {
console.log(`Toast message displayed ${i + 1}: ${toastText}`);
return true;
}
}
return false; }
Test.js
----------------------------------------------------------
const toastText = "Wrong OTP entered. Please enter the correct OTP";
const isToastDisplayed = await HelperClass.isToastMessageDisplayed(toastText);
expect(isToastDisplayed).to.be.true;