Appium 模拟

您可能需要测试使用相机拍摄照片或扫描条形码的应用程序,或者使用身份验证来保护登录或付款等敏感功能的应用程序。如果要测试的设备在物理上不可用,则会出现问题。使用模拟,您可以测试应用程序的这些方面,而无需访问物理设备。

注: 仅注入代码的应用程序支持模拟。要安装并启动注入代码的应用程序,请将 installPackageApp 功能设置为 true。

生物识别

您可以在 Appium 测试中模拟指纹和人脸识别 (仅 iOS) 身份验证。使用以下参数和值指定要用于仿真的数据。

模拟数据

参数
authResult

模拟结果:

  • 成功

  • 失败

  • 取消

authType

身份验证类型:

指纹

备注: 指纹 authType 也用于 FaceID。

authResultDetails

模拟失败或取消时的结果原因。当 authResult = Success 时,将该值保留为空。

authResult =失败

  • 无法识别
    正在使用的生物识别数据与注册的数据不匹配。例如,设备的所有者注册了他们的生物识别数据,而其他人尝试使用他们自己的数据解锁设备。

  • 锁定
    失败的尝试次数太多。
  • FingerIncomplete
    仅 Android : 手指移动太快。
  • 感应器脏
    仅 Android : 指纹传感器脏。
  • NoFingerprint 已注册
    仅 iOS : 否身份验证方法已在设备上注册。例如,设备的所有者没有注册他们的 TouchID/FaceID,但是正在测试的应用程序在某些时候需要 TouchID/FaceID。
 

authResult =取消

  • 用户
    用户取消了身份验证
  • 系统
    系统取消了身份验证。

操作

指定测试期间要执行的仿真类型:

参数
操作

身份验证

后退到顶部

照片、条形码和二维码模拟

您可以模拟拍摄照片,或扫描 Appium 测试中的条形码或二维码。使用摄影机模拟时,可以指定要使用的图像,而不是摄影机的实际输出。

参数
内容类型 图像
文件名
任何文件名,包括后缀。
上载介质 介质应以 base64 编码。
操作

正在执行的仿真类型:

  • 条码

  • 照相机

注: 要关闭摄像机模拟,请将 uploadMedia 设置为"0"。

后退到顶部

代码示例

以下部分提供了将 Digital Lab 摄像机和身份验证模拟用于 Appium 的代码示例。有关使用 Appium 和 Digital Lab, 的工作项目,请参阅 Digital Lab github 存储库

Android 身份验证和相机模拟- Java

示例代码使用 Java 客户端 v8。对于 Java 客户端 v7.x,请参阅 Digital Lab github repository 中的示例

Copy code
import comgooglecommonioResources;
import comgooglegsonGson;
import comgooglegsonJsonObject;
import ioappiumjava_clientAppiumBy;
import ioappiumjava_clientTouchAction;
import ioappiumjava_clientandroidAndroidDriver;
import ioappiumjava_clientandroidoptionsUiAutomator2Options;
import ioappiumjava_clienttouchoffsetPointOption;
import orgopenqaseleniumWebElement;
import orgopenqaseleniumremoteRemoteWebElement;
import javaawt.*;
import javaioIOException;
import javanetMalformedURLException;
import javanetURISyntaxException;
import javanetURL;
import javaniofileFiles;
import javaniofilePath;
import javaniofilePaths;
import javatimeDuration;
import javautilBase64;
import javautilHashMap;
import javautilObjects;
public class Simulation {
    private static AndroidDriver driver;
    private static String SERVER = "https://digitallab-server:8443";
    public static void main(String[] args) throws MalformedURLException {
        UiAutomator2Options caps = new UiAutomator2Options();
        capssetCapability("platformName", "Android");
        capssetCapability("udid", "8BSX1EDTD");
        capssetCapability("automationName", "UiAutomator2");
        capssetCapability("appPackage", "com.Advantage.aShopping");
        capssetCapability("appActivity", "com.Advantage.aShopping.SplashActivity");
        capssetCapability("uftm:oauthClientId", "oauth2-tGR1nN6ZxLQNMrKH4Hq9@opentext.com");
        capssetCapability("uftm:oauthClientSecret", "A3BNk1Tc4gbf7o2jDU5m");
        capssetCapability("uftm:tenantId", "999999999");
        //Simulations are supported only on packaged apps. The below capability instructs Digital Lab to install the packaged version of the app. Default value is false
        capssetCapability("uftm:installPackagedApp", true);
        driver = new AndroidDriver(new URL(SERVER + "/wd/hub"), caps);
        Systemoutprintln("Digital Lab session was successfully created [Android device]");
        try{
            //Implicit wait
            drivermanage().timeouts().implicitlyWait(DurationofSeconds(10));
            driverfindElement(AppiumByid("imageViewMenu")).click();
            driverfindElement(AppiumByid("textViewMenuUser")).click();
            WebElement username = driverfindElement(AppiumByxpath("//*[@resource-id='com.Advantage.aShopping:id/AosEditTextLoginUserName']/android.widget.EditText[1]"));
            usernameclick();
            usernamesendKeys("Mercury");
            WebElement password = driverfindElement(AppiumByxpath("//*[@resource-id='com.Advantage.aShopping:id/AosEditTextLoginPassword']/android.widget.EditText[1]"));
            passwordclick();
            passwordsendKeys("Mercury");
            driverfindElement(AppiumByid("buttonLogin")).click();
            Threadsleep(3000);
            String message = driverfindElement(AppiumByid("android:id/message")).getText();
            if(messagecontains("Would you like to use fingerprint authentication for logging in ?")){
                driverfindElement(AppiumByid("android:id/button1")).click();
                //Perform biometric simulation
                Systemoutprintln("Biometric simulation result:" + biometricSimulation("Success",""));
            }
            driverfindElement(AppiumByandroidUIAutomator("new UiSelector().textContains(\"LAPTOPS\")")).click();
            driverfindElement(AppiumByandroidUIAutomator("new UiSelector().textContains(\"HP CHROMEBOOK 14 G1(ENERGY STAR)\")")).click();
            int requiredSwipes = driverfindElements(AppiumByxpath("//*[@resource-id='com.Advantage.aShopping:id/linearLayoutImagesLocation']/android.widget.FrameLayout")).size();
            WebElement imageList = driverfindElement(AppiumByid("viewPagerImagesOfProducts"));
            for(int i = 1;i <= requiredSwipes;i++){
                swipeElement(((RemoteWebElement) imageList).getId(),"up", 1);
            }
            //load the photo before opening the camera
            Systemoutprintln("Photo simulation result:" + cameraSimulation("image","cat.png","camera"));
            imageListclick();
            //The steps below are performed on the device's camera and correspond to a device with Android 12
            //These steps may change depending on the device model/brand since the camera app might be different.
            driverfindElement(AppiumByaccessibilityId("Take photo")).click();
            driverfindElement(AppiumByaccessibilityId("Done")).click();
            //Barcode simulation sample usage:
            //System.out.println(cameraSimulation("image","QRCode.jpg","barcode"));
        }catch (Exception e){
            eprintStackTrace();
        }finally {
            if (driver != null) driverquit();
        }
    }
    /**
     * Biometric authentication simulation enable/update command.
     * @param authResult The simulate result: Failure, Success, or Cancel
     * @param authResultDetails The simulate reason when Failure/Cancel
     *     Failure: NotRecognized, Lockout, FingerIncomplete(Android only), SensorDirty(Android only), NoFingerprintRegistered(iOS only)
     *     Cancel: System, User
     * @return The result of ExecuteScript
     */
    private static String biometricSimulation(String authResult, String authResultDetails) throws InterruptedException {
        HashMap<String, Object> sensorSimulationMap = new HashMap<String, Object>();
        HashMap<String, String> simulationData = new HashMap<String, String>();
        simulationDataput("authResult", authResult);
        simulationDataput("authType", "Fingerprint");
        simulationDataput("authResultDetails", authResultDetails);

        sensorSimulationMapput("simulationData", simulationData);
        sensorSimulationMapput("action", "authentication");
        sensorSimulationMapput("action", "authentication");        

        //Execute the script and convert the result to a JSON string
        String simulationResult = new Gson().toJson(driverexecuteScript("mc:sensorSimulation", sensorSimulationMap));
        //Return just the message value from simulationResult
        return new Gson().fromJson(simulationResult, JsonObjectclass).get("message").getAsString();
    }
    /**
     *
     * @param contentType Image
     * @param fileName Any file name
     * @param action Action: barcode, camera
     * @return
     */
    private static String cameraSimulation(String contentType, String fileName, String action) throws IOException, URISyntaxException, InterruptedException {
        Path path = Pathsget(ObjectsrequireNonNull(ResourcesgetResource("photo/" + fileName)).toURI());
        byte[] bytes = FilesreadAllBytes(path);
        String encodedString = Base64getEncoder().encodeToString(bytes);
        HashMap<String, String> sensorSimulationMap =  new HashMap<>();
        sensorSimulationMapput("uploadMedia", encodedString);
        sensorSimulationMapput("contentType", contentType);
        sensorSimulationMapput("fileName", fileName);
        sensorSimulationMapput("action", action);
        //Execute the script and convert the result to a JSON string
        String simulationResult = new Gson().toJson(driverexecuteScript("mc:sensorSimulation", sensorSimulationMap));
        //Return just the message value from simulationResult
        return new Gson().fromJson(simulationResult, JsonObjectclass).get("message").getAsString();
    }
    /**
     *
     * @param elementId The id of the element to be swiped
     * @param direction Swipe direction. Mandatory value. Acceptable values are: up, down, left and right (case insensitive)
     * @param percent The size of the swipe as a percentage of the swipe area size. Valid values must be float numbers in range 0.1, where 1.0 is 100%
     */
    private static void swipeElement(String elementId, String direction, double percent){
        HashMap<String, Object> swipeMap =  new HashMap<>();
        swipeMapput("elementId", elementId);
        swipeMapput("direction", direction);
        swipeMapput("percent", percent);
        driverexecuteScript("mobile: swipeGesture", swipeMap);
    }
}

Android 身份验证和相机模拟- C#.Net

Copy code
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Enums;
using OpenQA.Selenium.Appium.Android;
using OpenQA.Selenium;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Drawing.Imaging;
using System.Drawing;
using Appium_Simulations.Resources;
using OpenQA.Selenium.Remote;

namespace Appium_Simulations
{
    public class Android
    {
        public static AndroidDriver driver;
        public static String DL_SERVER = "http://digitallab-server:8080";
        //Update the below variable to indicate whether you want to use Appium v2 or the default Appium v1
        private static Boolean useAppiumV2 = true;

        static void Main(string[] args)
        {            
            AppiumOptions appiumOptions = new AppiumOptions();

            //Digital Lab  embedded Appium capabilities                                                                                 
            appiumOptions.AddAdditionalAppiumOption("appium:udid", "8BSX1EDTD");            
            appiumOptions.AddAdditionalAppiumOption("appium:appPackage", "com.Advantage.aShopping");
            appiumOptions.AddAdditionalAppiumOption("appium:appActivity", "com.Advantage.aShopping.SplashActivity");
            appiumOptions.AddAdditionalAppiumOption("uftm:oauthClientId", "oauth2-UNmB6dXe4XNzJpjY4GSg@opentext.com");
            appiumOptions.AddAdditionalAppiumOption("uftm:oauthClientSecret", "3Rd1wgB0g71KBT6S2tv3");
            appiumOptions.AddAdditionalAppiumOption("uftm:tenantId", "999999999");

            //Simulations are supported only on packaged apps. The below capability instructs Digital Lab to install the packaged version of the app. Default value is false
            appiumOptions.AddAdditionalAppiumOption("uftm:installPackagedApp", true);
            System.Uri url = new System.Uri(stringFormat("{0}/wd/hub", DL_SERVER));            

            try
            {
                driver = new AndroidDriver(url, appiumOptions);
                System.Console.WriteLine("Digital Lab session was successfully created [Android device]");

                //Implicit wait
                driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
                driver.FindElement(MobileBy.Id("imageViewMenu")).Click();
                driver.FindElement(MobileBy.Id("textViewMenuUser")).Click();
                WebElement username = driver.FindElement(MobileBy.XPath("//*[@resource-id='com.Advantage.aShopping:id/AosEditTextLoginUserName']/android.widget.EditText[1]"));
                username.Click();
                username.SendKeys("Mercury");
                WebElement password = driver.FindElement(MobileBy.XPath("//*[@resource-id='com.Advantage.aShopping:id/AosEditTextLoginPassword']/android.widget.EditText[1]"));
                password.Click();
                password.SendKeys("Mercury");
                driver.FindElement(MobileBy.Id("buttonLogin")).Click();
                Thread.Sleep(3000);
                String message = driver.FindElement(MobileBy.Id("android:id/message")).Text;
                if (message.Contains("Would you like to use fingerprint authentication for logging in ?"))
                {
                    driver.FindElement(MobileBy.Id("android:id/button1")).Click();
                    //Perform biometric simulation
                    Console.WriteLine("Biometric simulation result:" + BiometricSimulation("Success", ""));
                }
                driver.FindElement(MobileBy.AndroidUIAutomator("new UiSelector().textContains(\"LAPTOPS\")")).Click();
                driver.FindElement(MobileBy.AndroidUIAutomator("new UiSelector().textContains(\"HP CHROMEBOOK 14 G1(ENERGY STAR)\")")).Click();
                int requiredSwipes = driver.FindElements(MobileBy.XPath("//*[@resource-id='com.Advantage.aShopping:id/linearLayoutImagesLocation']/android.widget.FrameLayout")).Count;
                WebElement imageList = driver.FindElement(MobileBy.Id("viewPagerImagesOfProducts"));
                for (int i = 1; i <= requiredSwipes; i++)
                {                                        
                    swipeElement(imageList.Location, imageList.Size, "up", 1);
                }
                //load the photo before opening the camera                
                Console.WriteLine("Photo simulation result:" + CameraSimulation(SimulationResources.cat, ImageFormat.Png, contentType: "image", fileName: "cat.png", action: "camera"));
                imageList.Click();
                //The steps below are performed on the device's camera and correspond to a device with Android 12.
                //These steps may change depending on the device model/brand since the camera app might be different.
                driver.FindElement(MobileBy.AccessibilityId("Take photo")).Click();
                driver.FindElement(MobileBy.AccessibilityId("Done")).Click();

                //Barcode simulation sample usage:
                //Console.WriteLine(CameraSimulation(SimulationResources.QRCode, ImageFormat.Png, contentType: "image", fileName: "QRCode.png", action: "barcode"));                
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
            }
            finally
            {
                if (driver != null)
                    driver.Quit();
            }
        }

        /// <summary>
        /// Biometric authentication simulation enable/update command.
        /// </summary>
        /// <param name="authResult">The simulate result, including Failure, Success, Cancel</param>
        /// <param name="authResultDetails">
        /// The simulate reason when Failure/Cancel
        /// Failure: NotRecognized, Lockout, FingerIncomplete(Android only), SensorDirty(Android only), NoFingerprintRegistered(iOS only)
        /// Cancel: System, User
        /// </param>
        /// <returns>The result of ExecuteScript</returns>
        public static string BiometricSimulation(string authResult, string authResultDetails = "")
        {
            Dictionary<string, object> sensorSimulationMap = new Dictionary<string, object>();
            Dictionary<string, string> simulationData = new Dictionary<string, string>
            {
                { "authResult", authResult },
                { "authType", "Fingerprint" },
                { "authResultDetails", authResultDetails }
            };
            sensorSimulationMap.Add("simulationData", simulationData);
            sensorSimulationMap.Add("action", "authentication");                       

            string simulationResult = JsonConvert.SerializeObject(driver.ExecuteScript("mc:sensorSimulation", sensorSimulationMap));
            return JToken.Parse(simulationResult)["message"].ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="picture"></param>
        /// <param name="format"></param>
        /// <param name="contentType">image</param>
        /// <param name="fileName"></param>
        /// <param name="action">Action: barcode, camera</param>
        /// <returns></returns>
        public static string CameraSimulation(Bitmap picture, ImageFormat format, string contentType, string fileName, string action)
        {
            MemoryStream ms = new MemoryStream();
            picture.Save(ms, format);
            Byte[] bytes = ms.ToArray();
            string encodeString = Convert.ToBase64String(bytes);

            Dictionary<string, string> sensorSimulationMap = new Dictionary<string, string>
            {
                { "uploadMedia", encodeString },
                { "contentType", contentType },
                { "fileName", fileName },
                { "action", action }
            };

            string simulationResult = JsonConvert.SerializeObject(driver.ExecuteScript("mc:sensorSimulation", sensorSimulationMap));
            return JToken.Parse(simulationResult)["message"].ToString();
        }


        /// <summary>
        /// Performs swipe on element
        /// </summary>        
        /// <param name="location">Object location</param>
        /// <param name="size">Object size</param>
        /// <param name="direction">Swipe direction. Mandatory value. Acceptable values are: up, down, left and right (case insensitive)</param>
        /// <param name="percent">The size of the swipe as a percentage of the swipe area size. Valid values must be float numbers in range 0..1, where 1.0 is 100%</param>

        private static void swipeElement(Point location, Size size, String direction, double percent)
        {            
            Dictionary<string, object> swipeMap = new Dictionary<string, object>
            {
                { "left", 0},
                { "top", 0},
                { "width", size.Width },
                { "height", size.Height + location.Y - 30},
                { "direction", direction },
                { "percent", percent }
            };
            
            driver.ExecuteScript("mobile: swipeGesture", swipeMap);
        }

    }
}

 

有关其他代码示例,请参阅 Appium 集成Appium 代码示例- Java