当前位置:网站首页>Sikulix选取相对位置的图片(进阶版)

Sikulix选取相对位置的图片(进阶版)

2022-06-22 13:17:00 qq_492448446

package com.welab.automation.projects.demo;

import io.appium.java_client.MobileBy;
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.service.local.AppiumDriverLocalService;
import io.appium.java_client.service.local.AppiumServiceBuilder;
import lombok.SneakyThrows;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.sikuli.script.Match;
import org.sikuli.script.Region;
import org.sikuli.script.Screen;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.util.Base64;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

import static io.appium.java_client.service.local.flags.GeneralServerFlag.LOG_LEVEL;
import static io.appium.java_client.service.local.flags.GeneralServerFlag.SESSION_OVERRIDE;

public class TestSikulix {
    public static final String WIN_DRIVER_PATH = "D:/Program Files/nodejs/node.exe";
    public static final String WIN_APPIUM_PATH = "C:/Users/jeff.xie/AppData/Roaming/npm/node_modules/appium/build/lib/main.js";
    public static final String MAC_DRIVER_PATH = "/usr/local/bin/node";
    public static final String MAC_APPIUM_PATH = "/usr/local/lib/node_modules/appium/build/lib/main.js";
    int width;
    int height;
    AndroidDriver driver;


    public static void main(String[] args) throws URISyntaxException, IOException {
        TestSikulix testOpenCV = new TestSikulix();
        testOpenCV.startMain();
    }

    public DesiredCapabilities setAndroidDesiredCapabilities(){
        DesiredCapabilities devices  = new DesiredCapabilities();
        devices.setCapability("platformName", "Android");
        devices.setCapability("deviceName","emulator-5554");
        devices.setCapability("platformVersion", "10");
        devices.setCapability("appPackage","com.android.settings");
        devices.setCapability("appActivity","com.android.settings.Settings");
        devices.setCapability("automation","uiautomator2");
        devices.setCapability("unicodeKeyboard", true);
        devices.setCapability("resetKeyboard",true);
        return devices;
    }

    public void getWindowWidthAbdHeight(){
        width = driver.manage().window().getSize().width;
        height = driver.manage().window().getSize().height;
    }

    @SneakyThrows
    public void startMain()  throws URISyntaxException, IOException {
        //需要打开appium server,并启动模拟器
        //driver= new AndroidDriver(new URL("http://localhost:4723/wd/hub"),setAndroidDesiredCapabilities());

        //不需要打开appium桌面版
        AppiumDriverLocalService service =startAppiumService();
        driver = new AndroidDriver(service.getUrl(), setAndroidDesiredCapabilities());

        Screen s = new Screen();
        // 设置未找到元素,自动等待时间10秒
        s.setAutoWaitTimeout(10);
        String project_path=System.getProperty("user.dir");
        System.out.println(System.getProperty("user.dir"));
        String path = project_path+ "\\src\\main\\java\\com\\welab\\automation\\projects\\demo\\Notifications.png";

        String target ="D:\\images\\test\\test01.png";

        getWindowWidthAbdHeight();
        Region r = new Region(0,0,width,height);
        Match match=r.exists(target);
        //Match match = r.find(target);

        Region region=match.highlight();
        String locations=region.toStringShort();
        String matchString = match.toStringShort();
        System.out.println("matchString:"+matchString);
        System.out.println("match.x:"+match.x);
        System.out.println("match.y:"+match.y);
        System.out.println("match.h:"+match.h);
        System.out.println("match.w:"+match.w);
        System.out.println("match.getCenter:"+match.getCenter());
        System.out.println("match.getScore(): "+match.getScore());

        System.out.println("region.x:"+region.x);
        System.out.println("region.y:"+region.y);
        System.out.println("region.h:"+region.h);
        System.out.println("region.w:"+region.w);
        System.out.println("region.getCenter:"+region.getCenter());
        System.out.println("locations: "+locations);
        System.out.println("match.getScore(): "+match.getScore());

// [log] CLICK on L[120,648]@S(0) (546 msec) // [log] highlight M[46,621 148x54]On(0) S 10000 for -1.0 secs // region.x:46 图片在界面左侧位置为46 // region.y:621 图片在界面过度位置为4621 // region.h:54 图片的高度 // region.w:148 图片的宽度 // region.getCenter:L[120,648]@S(0) // 点击的位置为图片中心点 左侧位置46 + 宽度 148/2 =120 高度位置621 + 图片高度 54/2 =648 // match.getScore(): 1.0 得分1.0 说明匹配为100%
        System.out.println(match.h);
        System.out.println(match.w);
        match.highlight();

        Thread.sleep(5000);
        s.click(target);
        Thread.sleep(5000);
        s.click("D:\\images\\test\\test02.png");
        System.out.println("pass");
    }

    public  void clickMobileElementByPicture(String picPath) throws URISyntaxException, IOException {
        File file = new File(picPath);
        String base64String = Base64.getEncoder().encodeToString(Files.readAllBytes(file.toPath()));
        By by= MobileBy.image(base64String);
        findMobileElement(by).click();
    }

    public MobileElement findMobileElement(By by) {
        return (MobileElement) driver.findElement(by);
    }

    private static AppiumDriverLocalService startAppiumService() {
        AtomicInteger port = new AtomicInteger();
        AppiumDriverLocalService service = null;
        service = new AppiumServiceBuilder()
                .usingAnyFreePort()
                .withIPAddress("0.0.0.0")
                .withArgument(SESSION_OVERRIDE)
                .withArgument(LOG_LEVEL, "error")
                .usingDriverExecutable(new File("D:\\Program Files\\nodejs\\node.exe"))
                .withAppiumJS(new File("C:\\Users\\jeff.xie\\AppData\\Roaming\\npm\\node_modules\\appium\\build\\lib\\main.js"))
                .build();
        Optional.ofNullable(service).ifPresent(s -> {
            s.start();
            port.set(s.getUrl().getPort());
        });
        AppiumDriverLocalService appiumDriverLocalService = service;
        return service;
    }

}


Sikulix选取相对位置的图片或对象
一般来说有这样的需求,我已经有了一个图片元素,在这个元素的周围会有一个动态显示的对象,我要去做一个点击或者是hover又或者是单纯把这个对象图片save到本地,留做下个页面点击的对象,在这种情况下就可以用到sikuli来解决。
这里我还是依照baidu首页做个例子,可能不是很典型,但是做例子是没问题的。
我先点击换肤按钮,然后在已知换肤图片的情况下,点取其他方位的图片,并save到本地留住成为下次脚本点击的对象。

1. 首先建立一个region对象,这个region是一个方形区域,我先默认成分辨率大小
Region r = new Region(0,0,1023,767);

2. 点击皮肤按钮
r.click("img/ChangeSK.png");

3. 这个我有一个皮肤的图片是在所有皮肤图片的中央
r.exists("img/SK1.png");
运行下,结果还是没问题的:
[debug] Region: exists: img/SK1.png has appeared

4. 把这个图片找到并作为一个Match对象,highlight并打印相似度,同时打印出width和height
Match SK1 = r.find("img/SK1.png");
System.out.println(baidu.getScore());
SK1.highlight();
System.out.println(SK1.h); 
System.out.println(SK1.w);
结果0.9999843239784241, 说明已经找到

5. 新建一个Location对象,来存放此对象在region中的坐标
Location Loc1 = SK1.getTarget();
注意描述一个图片就有四维,start x,start y,width,height.  这里的location是指的x+height/2, y+width/2, 也就是中心位置
这里我们需要一个工具来获取屏幕上的坐标,这样在手动测试的时候就能精准获取图片的相对位置,网上这样的工具很多,搜下就有了

6. 获取到Location之后,我就需要知道在这个SK1对象的上方的一个同样大小的图片,这里如何做呢:
Location Loc2 = Loc1.above(60);
通过工具得知上方图片的位置大概要高出60pix,所以新建一个location对象

7.因为我们已经知道上方图片的width和height,所以现在就需要新建一个Match对象就行了
Match SK2 = new Match(SK1);
SK2.setLocation(Loc2);//这样的做法是错误的,因为这里setLocation不是中心轴了,而是set成起始坐标了,应该这样:
SK2.y = SK2.y-60;

8,打印下相似度看是否找到
SK2.highlight();
System.out.println(SK2.getScore());
得分是1,没问题

9,把这个图片save到本地路径下
SK2.saveScreenCapture("img", "SK2");
SK2-1444961093063.png 保存名后面的应该是timestream,应该是避免覆盖,改下sikuli jar包里的源代码重新编译下就可以了。

这样和selenium结合起来就能大大增强case的覆盖率

原网站

版权声明
本文为[qq_492448446]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_30273575/article/details/125403526