• 使用appium和testng实现Android自动截图


    简单介绍

    需求场景是:当测试安卓应用的脚本得到失败结果时,对当前手机屏幕截图,便于查找问题。

    实现方式是:1)定义一个父类UITest,作为所有测试类的父类。在父类中UITest中定义一个截图的方法,所有的子类就都可以使用这个方法了。2)实现testng的ITestListener接口,参考这里,在这个接口的onTestFailure方法中调用测试类的截图方法。

    定义测试脚本的父类

    package main.java.com.dbyl.library.utils;
    
    /**
     * Created by wwh on 17/2/16.
     */
    /**
     *
     */
    
    
    import java.io.File;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    
    import io.appium.java_client.android.AndroidDriver;
    import org.apache.commons.io.FileUtils;
    import org.openqa.selenium.OutputType;
    import org.openqa.selenium.TakesScreenshot;
    
    
    /**
     * @author 
     *
     */
    public class UITest {
        private AndroidDriver driver;
        Log log = new Log(this.getClass());
    
        public AndroidDriver getDriver() {
            return driver;
        }
    
        /**
         * init test case
         *
         * @param driver
         */
        public void setDriver(AndroidDriver driver) {
            this.driver = driver;//把子类的driver传进来,更新父类driver
        }
    
        public void init(AndroidDriver driver) {
            setDriver(driver);
        }
        
    
        /**
         *  take screenshot
         */
        public void takeScreenShot() {
            SimpleDateFormat sf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
            Calendar cal = Calendar.getInstance();
            Date date = cal.getTime();
            String dateStr = sf.format(date);
            String path = this.getClass().getSimpleName() + "_" + dateStr + ".png";//用类名和日期作为截图的文件名
            takeScreenShot((TakesScreenshot) this.getDriver(), path);
        }
    
        /**
         * take screenshot
         * @param drivername
         * @param path
         */
        public void takeScreenShot(TakesScreenshot drivername, String path) {
            // this method will take screen shot ,require two parameters ,one is
            // driver name, another is file name
    
            log.info("take screenshot");
            File scrFile = drivername.getScreenshotAs(OutputType.FILE);
            // Now you can do whatever you need to do with it, for example copy
            try {
                log.info("save snapshot path is:"  + path);
                FileUtils.copyFile(scrFile, new File( path));
            } catch (Exception e) {
                log.error("Can't save screenshot");
                e.printStackTrace();
            } finally {
                log.info("screen shot finished");
            }
        }
    
    }

    上面代码中,使用了AndroidDriver类型的driver,适用于安卓应用测试脚本的父类。如果测试iOS应用,则使用iOSDriver类型的driver。

    继承父类的测试脚本

    package main.java.com.dbyl.library.utils;
    import io.appium.java_client.MobileElement;
    import io.appium.java_client.android.AndroidDriver;
    import io.appium.java_client.remote.AndroidMobileCapabilityType;
    import io.appium.java_client.remote.AutomationName;
    import io.appium.java_client.remote.MobileCapabilityType;
    import org.openqa.selenium.remote.CapabilityType;
    import org.openqa.selenium.remote.DesiredCapabilities;
    import org.testng.Assert;
    import org.testng.annotations.*;
    
    import java.io.File;
    import java.net.URL;
    
    
    /**
     * Created by wwh on 17/2/20.
     */
    @Listeners(main.java.com.dbyl.library.utils.CustomTestngListener.class)//通过注解调用我们自己实现的类
    public class TestScreenshot extends UITest{//继承父类UITest
        private AndroidDriver<MobileElement> driver;
    
        @Test
        public void Demo() throws Exception {
    // set up appium
            DesiredCapabilities capabilities = new DesiredCapabilities();
            capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.APPIUM);
    //for native app set null, for web test please set chrome or firefox
            capabilities.setCapability(CapabilityType.BROWSER_NAME, "");
            capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
            capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
    //simulator version 4.4
            capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "4.4");
    // if no need install don't add this
            File classpathRoot = new File("/Users/wwh/IdeaProjects");
    //        File classpathRoot = new File(System.getProperty("user.dir"));
            File appDir = new File(classpathRoot, "apps");
            File app = new File(appDir, "apppiumDemo.apk");
            capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
    
    //package name
            capabilities.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "cn.dbyl.appiumdemo");
    // // support Chinese
            capabilities.setCapability("unicodeKeyboard", "True");
            capabilities.setCapability("resetKeyboard", "True");
    // no need sign
            capabilities.setCapability("noSign", "True");
    //launcher activity
            capabilities.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, ".MainActivity");
            String url = "http://localhost:4723/wd/hub";
            driver = new AndroidDriver<MobileElement>(new URL(url), capabilities);
            super.init(driver);//在driver赋值后,需要将driver传给父类。
    
            MobileElement text = driver.findElementById("cn.dbyl.appiumdemo:id/text11");//这里将ID值由text1改为text11,所以这一句会报错
            Assert.assertEquals(text.getText(), "appiumDemo");
    
            MobileElement button = driver.findElementByClassName("android.widget.Button");
            button.click();
            text = driver.findElementById("cn.dbyl.appiumdemo:id/text1");
            Assert.assertEquals(text.getText(), "You just click the button");
    
        }
    
        @AfterTest
        public void Teardown(){
            driver.quit();
        }
    
    }

    TestListenerAdapter类实现了ITestListener接口。下面是重载TestListenerAdapter类的代码

    package main.java.com.dbyl.library.utils;
    
    /**
     * Created by wwh on 17/2/17.
     */
    import org.testng.ITestContext;
    import org.testng.ITestResult;
    import org.testng.TestListenerAdapter;
    
    /**
     *
     * @author 
     *
     */
    public class CustomTestngListener extends TestListenerAdapter {
        Log log = new Log(this.getClass());
    
        @Override
        public void onTestSuccess(ITestResult tr) {
            log.info("Test Success");
            super.onTestSuccess(tr);
        }
    
        @Override
        public void onTestFailure(ITestResult tr) {
            log.error("One Test Failure");
            super.onTestFailure(tr);
            takeScreenShot(tr);
        }
    
        private void takeScreenShot(ITestResult tr) {
            UITest b = (UITest) tr.getInstance();//ITestResult类型可以返回当前测试类的一个实例
            b.takeScreenShot();//借助这个实例,调用其截图方法
    
        }
    
        @Override
        public void onTestSkipped(ITestResult tr) {
            log.error("Test Skipped");
            super.onTestSkipped(tr);
        }
    
        @Override
        public void onTestStart(ITestResult result) {
            log.info("One Test Start");
            super.onTestStart(result);
        }
    
        @Override
        public void onStart(ITestContext testContext) {
            log.info("Before Any Test Start");
            super.onStart(testContext);
        }
    
        @Override
        public void onFinish(ITestContext testContext) {
            log.info("After All Tests Finish");
            super.onFinish(testContext);
        }
    
    }

    简单总结

    要想实现自动截图,需要做到三点:

    1. 继承带有截图方法的父类;
    2. 调用父类的init方法更新driver;
    3. 实现ITestListener接口或者重载TestListenerAdapter,并启用自定义的监听类;

    留下的问题

    测试Android应用和iOS应用需要使用不同的driver,进而需要定义两个测试类的父类。能不能只定义一个父类呢?

  • 相关阅读:
    [leetcode]259. 3Sum Smaller 三数之和小于目标值
    题型总结之K Sum
    [Leetcode]167. Two Sum II
    题型总结之Sliding Window
    [Leetcode]703. Kth Largest Element in a Stream 数据流中的第 K 大元素
    [Leetcode]307. Range Sum Query
    pycharm同一目录下无法import明明已经存在的.py文件
    python高级特性:迭代器与生成器
    self的含义,为什么类调用方法时需要传参数?
    git三:远程仓库GitHub
  • 原文地址:https://www.cnblogs.com/superbaby11/p/6426035.html
Copyright © 2020-2023  润新知