我们知道selenium支持多种定位器策略来在网页上查找元素。
但是我的要求不同,我有一些站点,其中硒支持的任何定位器不足以唯一地找到元素。
由于硒为创建自己的自定义定位器策略以查找元素提供了便利,因此我正在尝试创建 image 定位器,该定位器可以使用 base64 找到元素{1}}就像appium一样。
图像定位器的要点:
要完成此任务,我将创建自定义String
定位器,如下所示:
Image
现在测试用例为:
public class ByImage extends By {
String imageBase64String
/**
* @param imageBase64String
*/
public ByImage(String imageBase64String) {
this.imageBase64String = imageBase64String
}
@Override
public List<WebElement> findElement(SearchContext context) {
List<WebElement> els = findElements(context)
if (els) {
return els.get(0)
}
throw new NoSuchElementException("Element not found")
}
@Override
public List<WebElement> findElements(SearchContext context) {
//Get current screenshot
byte[] screenshotByte = ((TakesScreenshot)context).getScreenshotAs(OutputType.BYTES))
byte[] subImgToFindByte = DatatypeConverter.parseBase64Binary(imageBase64String)
//Convert buffred image to get height and width of subimage
BufferedImage bufferedSubImgToFind = ImageIO.read(new ByteArrayInputStream(subImgToFindByte ));
//Here I need a mechanism to get coordinates of sub image from screenshot
//Suppose I able to find x, y
double x
double y
//Now find element using coordinates
//Now calculate center point
int centerX = int(x + (bufferedSubImgToFind.getWidth() / 2))
int centerY = int(y + (bufferedSubImgToFind.getHeight() / 2))
JavascriptExecutor js = ((JavascriptExecutor)context)
return js.executeScript("return document.elementsFromPoint(arguments[0], arguments[1]);", centerX, centerY)
}
}
除了能够从WebDriver driver = new ChromeDriver()
driver.get("<URL>")
WebElement elementByImage = driver.findElement(new ByImage("<Base64 String of the subimage>"))
检测subimage
的确切坐标以使用坐标查找元素的更好的库之外,我能够实现所有功能。
有人可以建议我一种更好的方法来完成此任务吗?
答案 0 :(得分:2)
您可以选择其他选项,例如:
答案 1 :(得分:0)
为不熟悉Java绑定和OpenCV的用户添加另一个选项:Selenium IDE++包含内置的图像识别命令:
XClick (image)
XMove (image)
XClick (ocr=text)
有关更多详细信息,请参见UI testing页。您可以通过command line从Java调用它。
答案 2 :(得分:-1)
按照@Dmitri的建议,我要使用Java Bindings for OpenCV。
download appropriate OpenCV并将其提取到classpath
中,并尝试获取坐标为:
import org.opencv.core.Core;
import org.opencv.core.Core.MinMaxLocResult;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.Point;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
byte[] screenshotByte = ((TakesScreenshot)context).getScreenshotAs(OutputType.BYTES))
byte[] subImgToFindByte = DatatypeConverter.parseBase64Binary(imageBase64String)
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat source = Imgcodecs.imdecode(new MatOfByte(screenshotByte), Imgcodecs.IMREAD_UNCHANGED);
Mat template = Imgcodecs.imdecode(new MatOfByte(subImgToFindByte), Imgcodecs.IMREAD_UNCHANGED);
int result_cols = source.cols() - template.cols() + 1;
int result_rows = source.rows() - template.rows() + 1;
Mat outputImage = new Mat(result_rows, result_cols, CvType.CV_32FC1);
// Template matching method
Imgproc.matchTemplate(source, template, outputImage, Imgproc.TM_SQDIFF_NORMED);
MinMaxLocResult mmr = Core.minMaxLoc(outputImage);
// Now get the point
Point point = mmr.minLoc;
double x = point.x;
double y = point.y;
//Now get the find the element using x, y after calculating center point.
int centerX = int(x + (bufferedSubImgToFind.getWidth() / 2));
int centerY = int(y + (bufferedSubImgToFind.getHeight() / 2));
WebElement el = js.executeScript("return document.elementFromPoint(arguments[0], arguments[1]);", centerX, centerY);
希望对所有人都有帮助。