杭州第一期_UI 自动化进阶_20180701

有问题请回帖

下载地址

selenium下载地址
https://goo.gl/4g538W
http://shell.testing-studio.com/download/selenium/

appium grid的支持
https://github.com/appium/appium/blob/master/docs/en/advanced-concepts/grid.md

参考命令

tcpdump -i any port 4723 -w tcpdump.log

gem install em-proxy
em-proxy -l 5723 -r 127.0.0.1:4723 -v


#启动hub
java -jar ~/DownloadsMacBook-Pro-2:~ seveniruby$ java -jar ~/Downloads/selenium-server-standalone-3.13.0.jar -role hub
#启动node注册到hub
java -jar ~/Downloads/selenium-server-standalone-3.13.0.jar  -role node -hub http://192.168.31.99:4444/grid/register

#appium注册为node
appium --nodeconfig  android_1.json

参考用例代码

    @Test
    public void chrome() throws IOException {
        DesiredCapabilities capabilities=new DesiredCapabilities();
        ChromeOptions chromeOptions=new ChromeOptions();
        //chromeOptions.addArguments("headless");
        //chromeOptions.addArguments("window-size=400,1024");
        //chromeOptions.addArguments("user-agent=\\"Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Mobile Safari/537.36\\"");
        capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);

        RemoteWebDriver driver=new RemoteWebDriver(new URL("http://127.0.0.1:5555/wd/hub"), capabilities);
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("http://www.baidu.com");
        FileUtils.copyFile(driver.getScreenshotAs(OutputType.FILE), new File("1.png"));
    }

appium node配置

{
  "capabilities":
      [
        {
          "browserName": "chrome",
          "version": "6.0",
          "maxInstances": 1,
          "platform": "android"
        }
      ],
  "configuration":
  {
    "cleanUpCycle": 2000,
    "timeout": 30000,
    "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
    "url": "http://192.168.31.99:4723/wd/hub",
    "host": "192.168.31.99",
    "port": 4723,
    "maxSession": 1,
    "register": true,
    "registerCycle": 5000,
    "hubPort": 4444,
    "hubHost": "192.168.31.99",
    "hubProtocol": "http"
  }
}

微信小程序测试

    @Test
    public void testDianPing() throws IOException, InterruptedException {

        String processName = "com.tencent.mm:appbrand0";
        String packageName = "com.tencent.mm";
        String activityName = ".ui.LauncherUI";
        DesiredCapabilities caps = new DesiredCapabilities();

        caps.setCapability("deviceName", "dd");
        caps.setCapability("automationName", "uiautomator2");
        caps.setCapability("appPackage", packageName);
        caps.setCapability("appActivity", activityName);
        //如果没有这个设置你的微信聊天记录就会被清空
        caps.setCapability("noReset", true);
        //caps.setCapability("dontStopAppOnReset", true);
        caps.setCapability("chromedriverExecutableDir", "/Users/seveniruby/projects/chromedriver/2.29");
        caps.setCapability("showChromedriverLog", true);
        //低版本的chromedriver在高版本的android上有个兼容性的bug,需要自己定制解决方案
        //caps.setCapability("adbPort", 5038);

        //todo: appium java client 6.0.0 有多个bug,待修复
        ChromeOptions chromeOptions = new ChromeOptions();
        //chromeOptions.setExperimentalOption("androidUseRunningApp", true);
        //chromeOptions.setExperimentalOption("androidPackage", packageName);
        //chromeOptions.setExperimentalOption("androidActivity", activityName);
        chromeOptions.setExperimentalOption("androidProcess", processName);
        //caps.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
        caps.setCapability("chromeOptions", chromeOptions);
        //todo: 6.0.0独有的bug,会自动设置browserName
        caps.setCapability("browserName", "");
        System.out.println(caps.asMap());

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

        //todo: 5.0.3不支持1.8.1的timeout接口
        //driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        Thread.sleep(5000);
        driver.findElementByXPath("//*[@text='通讯录']");
        //滑动
        swipe(driver);

        System.out.println("点击小程序");
        driver.findElementByXPath("//*[contains(@text, '点评')]").click();

        System.out.println("打印上下文");
        for (int i = 0; i < 3; i++) {
            System.out.println(driver.getContextHandles());
            Thread.sleep(1000);
        }

        System.out.println("切换上下文到 " + "WEBVIEW_" + processName);
        driver.context("WEBVIEW_" + processName);
        System.out.println(driver.getContextHandles());
        System.out.println(driver.getContext());
        System.out.println(driver.getPageSource());

        System.out.println("打印上下文,寻找小程序界面");
        System.out.println(driver.getWindowHandles());
        for (String window : driver.getWindowHandles()) {
            driver.switchTo().window(window);
            System.out.println("windows=" + window);
            String source = driver.getPageSource();
            if (source.contains("<wx-view")) {
                System.out.println(source);
                break;
            }
        }
        driver.findElementByXPath("//*[contains(text(), '外卖')]").click();
        //6.0 beta5 修复了timeout问题

    }



/*
    public void swipe(AppiumDriver driver) {

        Dimension size = driver.manage().window().getSize();
        System.out.println(size);
        new TouchAction(driver)
                .press(
                        (int) (size.getWidth() * 0.5),
                        (int) (size.getHeight() * 0.3)
                )
                .waitAction(Duration.ofSeconds(2))
                .moveTo(

                        (int) (size.getWidth() * 0.5),
                        (int) (size.getHeight() * 0.9)
                )
                .release()
                .perform();
    }*/





     public void swipe(AppiumDriver driver) {
     Dimension size = driver.manage().window().getSize();
     System.out.println(size);
     new TouchAction(driver)
     .press(
     PointOption.point(
     (int) (size.getWidth() * 0.5),
     (int) (size.getHeight() * 0.3)
     )
     )
     .waitAction(
     WaitOptions.waitOptions(
     Duration.ofSeconds(2)
     )
     )
     .moveTo(
     PointOption.point(
     (int) (size.getWidth() * 0.5),
     (int) (size.getHeight() * 0.9))
     )
     .release()
     .perform();
     }

PageObject

package xueqiu4.page;

import io.appium.java_client.AppiumDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

public class Page首页 {
    private AppiumDriver<WebElement> driver;
    By 自选=By.xpath("//*[@text='自选']");
    By 问答广场 =By.xpath("//*[@text='问答广场']");
    By 跳过=By.xpath("//*[@text='跳过']");
    public Page自选 进入自选() throws InterruptedException {
        Thread.sleep(5000);
        driver.findElement(跳过).click();
        Thread.sleep(2000);
        driver.findElement(自选).click();
        return new Page自选(driver);
    }
    public Page首页(AppiumDriver driver){
        this.driver=driver;
    }

}

package xueqiu4.page;

import io.appium.java_client.AppiumDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import java.util.ArrayList;
import java.util.List;

public class Page自选 {
    private AppiumDriver<WebElement> driver;
    By 股票=By.xpath("//*[@text='股票']");
    By 沪深=By.xpath("//*[@text='沪深']");
    By stockName=By.id("stockName");
    List<String> stocks=new ArrayList<>();

    public List<String> get沪深股票(){
        driver.findElement(股票).click();
        driver.findElement(沪深).click();
        for(WebElement element: driver.findElements(stockName)){
            stocks.add(element.getText());
        };
        return stocks;
    }
    public Page自选(AppiumDriver driver){
        this.driver=driver;
    }
}

package xueqiu4.testcase;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.remote.DesiredCapabilities;
import xueqiu4.page.Page首页;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
import static org.hamcrest.number.OrderingComparison.*;

public class Test自选 {
    public static AppiumDriver driver;
    @BeforeClass
    public static void beforeClass() throws MalformedURLException, InterruptedException {

        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("platformName", "Android");
        capabilities.setCapability("deviceName", "iPhone 6");
        capabilities.setCapability("appPackage", "com.xueqiu.android");
        capabilities.setCapability("appActivity", ".view.WelcomeActivityAlias");
        capabilities.setCapability("automationName", "uiautomator2");
        capabilities.setCapability("noReset", false);
        capabilities.setCapability("chromedriverExecutableDir", "/Users/seveniruby/projects/chromedriver/2.20");

        driver=new AndroidDriver<AndroidElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
        driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
    }

    @Test
    public void test沪深股票() throws InterruptedException {
        Page首页 page首页=new Page首页(driver);
        List<String> stocks=page首页.进入自选().get沪深股票();
        assertThat(stocks.size(), greaterThan(5));

    }
}

基于Java注解或者Python装饰器模式的代码

package pages.xueqiudemo;

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

public class MainPage {
    @FindBy(xpath = "//*[@text='自选']")
    WebElement 自选;
    @FindBy(xpath = "//*[@text='行情']")
    WebElement 行情;

    @FindBy(id = "cancel")
    WebElement cancel;

    public Page自选 goto自选(){
        cancel.click();
        自选.click();
        return new Page自选();
    }
}

作业

进入雪球的行情页,断言上证指数指数超过3000点。