• Appium PageObject


    原文地址http://blog.csdn.net/TalorSwfit20111208/article/details/77434950

    由于无法联系上您,在此分享您的文章,希望谅解!

    Appium PageObject 直接沿用了Selenium的PageObject设计模式,

    PageObject主要优点如下:

    一、将UI元素与逻辑分离方便后期维护

    二、减少代码冗余

    三、增强代码可读性

    来看个例子

    没有使用PO设计模式的代码如下:

    [java] view plain copy
     
    1. @Test  
    2. public void twoPlusTwoOperation() {  
    3.   
    4.     /* 获取控件*/  
    5.     MobileElement buttonTwo = (MobileElement)(driver.findElement(By.id("net.ludeke.calculator:id/digit2")));  
    6.     MobileElement buttonPlus = (MobileElement)(driver.findElement(By.id("net.ludeke.calculator:id/plus")));  
    7.     MobileElement buttonEquals = (MobileElement)(driver.findElement(By.id("net.ludeke.calculator:id/equal")));  
    8.     MobileElement resultField = (MobileElement)(driver.findElement(By.xpath("//android.widget.EditText[1]")));  
    9.   
    10.     /* 计算2+2*/  
    11.     buttonTwo.click();  
    12.     buttonPlus.click();  
    13.     buttonTwo.click();  
    14.     buttonEquals.click();  
    15.   
    16.     /* 检查在给定的时间内是否显示要查找的控件 */  
    17.     new WebDriverWait(driver, 30).until(ExpectedConditions.textToBePresentInElement(resultField, EXPECTED_RESULT_FOUR));  
    18.   
    19. }  

    使用了PO设计模式的代码如下

    [java] view plain copy
     
    1. @Test  
    2. public void twoPlusTwoOperation() {  
    3.   
    4.     app.calculatorScreen().addTwoAndTwo();  
    5.     assertTrue(app.calculatorScreen().isResultCorrect("4"));  
    6.   
    7. }  

    我们注意到的第一个最直接的变化是测试方法的长度。使用PageObject模式编写的测试方法几乎总是比原始的方法短(对于较长的测试而言更短)。如果你继续阅读,你会注意到,这不仅是因为我们在addTwoAndTwo方法中包装了所有的按钮。
    可读性怎么样?再次通过这两种方法,问问自己在哪种情况下更容易理解发生了什么。另外,请注意我们如何在第二种方法中真的不需要注释,因为指定与Page Object具有的交互的方法具有重要的名称。
    通过将低级操作包含在专用方法中,我们现在有了不直接引用任何WebDriver API的测试方法。在编写第一个PageObject测试方法时,请使用缺少引用低级API的导入语句作为根据模式进行处理的指标。
    这种方法给了我们另一个不容忽视的优点:通过隐藏单一实用程序方法的技术复杂性,PageObject模式使得用户交互的流程变得明显。对于更长,更复杂的测试,以及我们编写测试的整个方式的转换,这特别有用。一旦实现了应用程序屏幕的基本交互,编写测试方法基本上只是通过调用正确名称所指的方法来复制用例。这就是为什么你应该努力为他们选择最好的名字。

    PageObject控件定位

    pageobject控件定位是使用注解方式来定位的,如下

    # WebElement/列表 WebElement 字段可以这样定位:

    使用@FindBy注解

    [java] view plain copy
     
    1. import org.openqa.selenium.support.FindBy;  
    2. import org.openqa.selenium.WebElement;  
    3. @FindBy(someStrategy)//用来定位浏览器或者webview UI  
    4. //也可以用来定位native 应用,当没有定义其他定位策略时  
    5. WebElement someElement;@FindBy(someStrategy) //用来定位浏览器或者webview UI  
    6. //也可以用来定位native 应用,当没有定义其他定位策略时  
    7. List<WebElement> someElements;//定位包含相同控件属性的控件  

    使用@AndroidFindBy来定位

    [java] view plain copy
     
    1. import io.appium.java_client.android.AndroidElement;  
    2. import org.openqa.selenium.remote.RemoteWebElement;  
    3. import io.appium.java_client.pagefactory.*;  
    4.   
    5. @AndroidFindBy(someStrategy) //用Android UI Automator来定位Android UI  
    6. AndroidElement someElement;  
    7.   
    8. @AndroidFindBy(someStrategy) //用Android UI Automator来定位Android UI  
    9.   
    10. List<AndroidElement> someElements;  


    多种组合查找策略

    [java] view plain copy
     
    1. import org.openqa.selenium.remote.RemoteWebElement;  
    2. import io.appium.java_client.pagefactory.*;  
    3. import org.openqa.selenium.support.FindBy;  
    4. import org.openqa.selenium.support.FindByAll;  
    5.   
    6.   
    7. import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE;  
    8.   
    9. @HowToUseLocators(androidAutomation = ALL_POSSIBLE, iOSAutomation = ALL_POSSIBLE)  
    10. @FindAll{@FindBy(someStrategy1), @FindBy(someStrategy2)})   
    11. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)   
    12. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)   
    13. RemoteWebElement someElement;  
    14.   
    15. @HowToUseLocators(androidAutomation = ALL_POSSIBLE, iOSAutomation = ALL_POSSIBLE)  
    16. @FindAll({@FindBy(someStrategy1), @FindBy(someStrategy2)})   
    17. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)  
    18. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)  
    19. List<RemoteWebElement> someElements;  


    ## 也可以用下面这种方式: 

    [java] view plain copy
     
    1. import org.openqa.selenium.remote.RemoteWebElement;  
    2. import io.appium.java_client.pagefactory.*;  
    3. import org.openqa.selenium.support.FindBy;  
    4. import org.openqa.selenium.support.FindByAll;  
    5.   
    6. import static io.appium.java_client.pagefactory.LocatorGroupStrategy.CHAIN;  
    7. import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE;  
    8.   
    9. @HowToUseLocators(androidAutomation = CHAIN, iOSAutomation = ALL_POSSIBLE)  
    10. @FindAll{@FindBy(someStrategy1), @FindBy(someStrategy2)})   
    11. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)   
    12. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)   
    13. RemoteWebElement someElement;  
    14.   
    15. @HowToUseLocators(androidAutomation = CHAIN, iOSAutomation = ALL_POSSIBLE)  
    16. @FindAll({@FindBy(someStrategy1), @FindBy(someStrategy2)})   
    17. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)  
    18. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)  
    19. List<RemoteWebElement> someElements;  


    或者

    [java] view plain copy
     
    1. import org.openqa.selenium.remote.RemoteWebElement;  
    2. import io.appium.java_client.pagefactory.*;  
    3. import org.openqa.selenium.support.FindBy;  
    4. import org.openqa.selenium.support.FindByAll;  
    5.   
    6. import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE;  
    7.   
    8. @HowToUseLocators(iOSAutomation = ALL_POSSIBLE)  
    9. @FindAll{@FindBy(someStrategy1), @FindBy(someStrategy2)})   
    10. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2) //this is the chain   
    11. //by default  
    12. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)   
    13. RemoteWebElement someElement;  
    14.   
    15. @HowToUseLocators(iOSAutomation = ALL_POSSIBLE)  
    16. @FindAll({@FindBy(someStrategy1), @FindBy(someStrategy2)})   
    17. @AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2) //this is the chain   
    18. //by default  
    19. @iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)  
    20. List<RemoteWebElement> someElements;  

    应用PO查找

    # Appium Java client使用了AppiumFieldDecorator来融合了Selenium PageFactory 

    对象字段结构如下: 

    [java] view plain copy
     
    1. import io.appium.java_client.pagefactory.*;  
    2. import org.openqa.selenium.support.PageFactory;  
    3.   
    4. PageFactory.initElements(new AppiumFieldDecorator(searchContext   
    5.               /*searchContext is a WebDriver or WebElement 
    6.               instance */),   
    7.               pageObject //对象类的一个实例  
    8. );  
    [java] view plain copy
     
    1. import io.appium.java_client.pagefactory.*;  
    2. import org.openqa.selenium.support.PageFactory;  
    3. import java.util.concurrent.TimeUnit;  
    4.   
    5. PageFactory.initElements(new AppiumFieldDecorator(searchContext,   
    6.               /*searchContext is a WebDriver or WebElement 
    7.               instance */  
    8.         15, //默认为所有查找策略的隐式等待时间  
    9.         TimeUnit.SECONDS),   
    10.             pageObject //对象类的一个实例  
    11.   
    12. );  
    [java] view plain copy
     
    1. import io.appium.java_client.pagefactory.*;  
    2. import org.openqa.selenium.support.PageFactory;  
    3. import java.util.concurrent.TimeUnit;  
    4.   
    5. PageFactory.initElements(new AppiumFieldDecorator(searchContext,   
    6.               /*searchContext is a WebDriver or WebElement 
    7.               instance */  
    8.         new TimeOutDuration(15, //默认为所有查找策略的隐式等待时间  
    9.   
    10.         TimeUnit.SECONDS)),   
    11.             pageObject //对象类的一个实例  
    12.   
    13. );  


    来看个经典计算器程序在PageObject中的实际应用

    项目结构
    安装程序的核心组件将是以下类:

    • AbstractTest:我们在其中设置测试阶段;
    • AppiumDriverBuilder:设置所需的功能并实例化驱动程序;
    • 我们调用的应用程序类访问我们的Screen对象;
    • AbstractScreen,包含您的Screen对象之间的所有共享方法;
    • Screen类包含表示用户与被测试应用程序交互的方法;
    • 测试类包含一个或多个测试,写成屏幕方法调用序列。

    为了进一步澄清项目结构,您可以将这些类组织成包。在一个实用程序包中,您可以包括您的AppiumDriverBuilder类以及您创建的其他实用程序类。您也可以将AbstractScreen类和其他Screen类放在屏幕包中。项目结构如下:


    AbstractTest
    在项目的中心是AbstractTest类。这里我们定义我们的测试套件方法,它将在每次测试运行之前执行。这里我们做两件非常重要的事情:

    1. 负责初始化负责连接到Appium服务器的驱动程序;
    2. 实例化了App类,这将允许我们访问我们想要测试的应用程序的单个屏幕;
    [java] view plain copy
     
    1. package com.test.calculatortest;  
    2.   
    3. import com.test.calculatortest.Calculator;  
    4. import com.test.calculatortest.util.AppiumDriverBuilder;  
    5.   
    6. import io.appium.java_client.AppiumDriver;  
    7.   
    8. import org.junit.Before;  
    9.   
    10. import java.net.MalformedURLException;  
    11. import java.net.URL;  
    12.   
    13. public abstract class AbstractTest {  
    14.   
    15.     private AppiumDriver<?> driver;  
    16.     protected Calculator app;  
    17.   
    18.     /* Establish a connection to TestObject, or to a local device test is local. */  
    19.     @Before  
    20.     public void connect() throws MalformedURLException {  
    21.   
    22.         this.driver = AppiumDriverBuilder.forAndroid()  
    23.                 .withEndpoint(new URL("http://127.0.0.1:4723/wd/hub"))  
    24.                 .build("com.android.calculator2", ".Calculator");  
    25.         //实例化应用类  
    26.         app = new Calculator(driver);  
    27.   
    28.     }  
    29.   
    30. }  

    AppiumDriverBuilder
    它基本上是一个支持类,负责配置和实例化的Appium驱动程序。

    [java] view plain copy
     
    1. package com.test.calculatortest.util;  
    2.   
    3. import io.appium.java_client.AppiumDriver;  
    4. import io.appium.java_client.android.AndroidDriver;  
    5. import io.appium.java_client.android.AndroidElement;  
    6.   
    7. import org.openqa.selenium.remote.DesiredCapabilities;  
    8.   
    9. import java.net.URL;  
    10.   
    11. public abstract class AppiumDriverBuilder<SELF, DRIVER extends AppiumDriver<?>> {  
    12.   
    13.   
    14.   
    15.     public static AndroidDriverBuilder forAndroid() {  
    16.         return new AndroidDriverBuilder();  
    17.     }  
    18.   
    19.     public static class AndroidDriverBuilder extends AppiumDriverBuilder<AndroidDriverBuilder, AndroidDriver<?>> {  
    20.   
    21.         DesiredCapabilities capabilities = new DesiredCapabilities();  
    22.   
    23.         @Override  
    24.         public AndroidDriver<?> build(String appPackage,String appActivity) {  
    25.   
    26.               
    27.               
    28.               
    29.             capabilities.setCapability("platformName", "Android");  
    30.             //使用Android模拟器  
    31.             capabilities.setCapability("deviceName", "testDevice");  
    32.             //使用Android模拟器  
    33.             capabilities.setCapability("platformVersion", "4.4.4");  
    34.             //不重新安装应用  
    35.             capabilities.setCapability("noReset",true);  
    36.             //待测包名及首次启动的页面  
    37.             capabilities.setCapability("appPackage", appPackage);  
    38.             capabilities.setCapability("appActivity", appActivity);  
    39.             //使用appium Unicode键盘输入法,输入完毕后重置输入法  
    40.             capabilities.setCapability("unicodeKeyboard", true);  
    41.             capabilities.setCapability("resetKeyboard", true);  
    42.               
    43.             capabilities.setCapability("deviceReadyTimeout",30);  
    44.   
    45.             return new AndroidDriver<AndroidElement>(endpoint, capabilities);  
    46.   
    47.         }  
    48.   
    49.       
    50.   
    51.     }  
    52.   
    53.     protected URL endpoint;  
    54.   
    55.     @SuppressWarnings("unchecked")  
    56.     public SELF withEndpoint(URL endpoint) {  
    57.         this.endpoint = endpoint;  
    58.   
    59.         return (SELF) this;  
    60.     }  
    61.   
    62.     public abstract DRIVER build(String appPackage,String appActivity);  
    63.   
    64. }  

    应用类
    测试中的另一个中心类将是Application类(我们简单的命名为我们正在测试的应用程序的名称)。这个类的功能是提供屏幕(正如我们之前所说的,Page对象)到需要访问它们的功能的方法(屏幕类中的测试方法)。

    [java] view plain copy
     
    1. package com.test.calculatortest;  
    2.   
    3.   
    4. import com.test.calculatortest.screen.CalculatorScreen;  
    5.   
    6.   
    7. import io.appium.java_client.AppiumDriver;  
    8. /* 
    9.  * 应用类,返回各个操作页面类 
    10.  */  
    11. public class Calculator {  
    12.   
    13.   
    14.     private final AppiumDriver<?> driver;  
    15.   
    16.   
    17.     public Calculator(AppiumDriver<?> driver) {  
    18.         this.driver = driver;  
    19.     }  
    20.   
    21.   
    22.     public CalculatorScreen calculatorScreen() {  
    23.         return new CalculatorScreen(driver);  
    24.     }  
    25.   
    26.   
    27. }  

    AbstractScreen类

    AbstractScreen类将包含Screen对象之间共享的所有方法。这些可能是通用目的的方法,可以执行多个点(滑动,滚动)与应用程序交互所需的手势,这些手段隐藏了一些更为复杂的代码,从而增加了测试方法的可读性,同步方法等。

    [java] view plain copy
     
    1. package com.test.calculatortest.screen;  
    2.   
    3. import io.appium.java_client.AppiumDriver;  
    4. import io.appium.java_client.MobileElement;  
    5. import io.appium.java_client.pagefactory.AppiumFieldDecorator;  
    6. import org.openqa.selenium.By;  
    7. import org.openqa.selenium.OutputType;  
    8. import org.openqa.selenium.support.PageFactory;  
    9. import org.openqa.selenium.support.ui.ExpectedConditions;  
    10. import org.openqa.selenium.support.ui.WebDriverWait;  
    11.   
    12. public abstract class AbstractScreen {  
    13.   
    14.     protected final AppiumDriver<?> driver;  
    15.   
    16.     public AbstractScreen(AppiumDriver<?> driver) {  
    17.         this.driver = driver;  
    18.   
    19.         PageFactory.initElements(new AppiumFieldDecorator(driver), this);  
    20. }  
    21.   
    22.     public MobileElement findElementWithTimeout(By by, int timeOutInSeconds) {  
    23.         return (MobileElement)(new WebDriverWait(driver, timeOutInSeconds)).until(ExpectedConditions.presenceOfElementLocated(by));  
    24.     }  
    25.   
    26.     protected void takeScreenShot(){  
    27.         driver.getScreenshotAs(OutputType.BASE64);  
    28.     }  
    29.   
    30. }  

    注意
    PageFactory.initElements(new AppiumFieldDecorator(driver), this);这句,这可以让你使用注释来抓取UI元素,因此请勿忘记将其包含在您的设置中!

    屏幕类
    屏幕类代表应用程序的屏幕。在这里获取UI元素并与代表可能与用户界面交互的方法与其进行交互,例如打开菜单并选择项目,填写某些字段并按下提交按钮,向下滚动列表并选择正确的元素这样,你的测试方法将只是不同屏幕上的一系列用户交互。这将使你的测试易于维护和扩展。

    [java] view plain copy
     
    1. package com.test.calculatortest.screen;  
    2.   
    3. import io.appium.java_client.AppiumDriver;  
    4. import io.appium.java_client.MobileElement;  
    5. import io.appium.java_client.pagefactory.AndroidFindBy;  
    6. import org.openqa.selenium.TimeoutException;  
    7. import org.openqa.selenium.support.ui.ExpectedConditions;  
    8. import org.openqa.selenium.support.ui.WebDriverWait;  
    9.   
    10. public class CalculatorScreen extends AbstractScreen {  
    11.   
    12.     @AndroidFindBy(id = "com.android.calculator2:id/digit2")  
    13.     private MobileElement buttonTwo;  
    14.   
    15.     @AndroidFindBy(id = "com.android.calculator2:id/plus")  
    16.     private MobileElement buttonPlus;  
    17.   
    18.     @AndroidFindBy(id = "com.android.calculator2:id/equal")  
    19.     private MobileElement buttonEquals;  
    20.   
    21.     @AndroidFindBy(xpath = "//android.widget.EditText[1]")  
    22.     private MobileElement resultField;  
    23.   
    24.     public CalculatorScreen(AppiumDriver<?> driver) {  
    25.         super(driver);  
    26.     }  
    27.   
    28.     public void addTwoAndTwo() {  
    29.   
    30.         buttonTwo.click();  
    31.         buttonPlus.click();  
    32.         buttonTwo.click();  
    33.         buttonEquals.click();  
    34.   
    35.     }  
    36.   
    37.     public boolean isResultCorrect(String result) {  
    38.   
    39.         try {  
    40.   
    41.             /* Check if within given time the correct result appears in the designated field. */  
    42.             (new WebDriverWait(driver, 30)).until(ExpectedConditions.textToBePresentInElement(resultField, result));  
    43.             return true;  
    44.   
    45.         } catch (TimeoutException e) {  
    46.   
    47.             return false;  
    48.   
    49.         }  
    50.   
    51.     }  
    52.   
    53. }  

    除了刚刚描述的应用程序的显着“主屏幕”之外,我们还可以创建另一个表示计算器应用程序的“高级面板”的程序,这基本上是自己的屏幕。在此屏幕中引用的UI元素将是计算器的符号/函数。
    你可以为应用程序的每个屏幕创建一个Screen对象,也可以决定仅对真正重要的屏幕执行此操作。这两种方法都有其优点和缺点,但请记住,可以使用太多屏幕的应用程序来处理,另一方面,在一个Screen对象中抽取太多的屏幕可能会导致混乱。
    测试类
    您的测试按照扩展AbstractTest的类进行分组。这允许您抓住应用程序的任何屏幕,并通过您编写的方法与其进行交互。

    [java] view plain copy
     
    1. package com.test.calculatortest;  
    2.   
    3.   
    4. import org.junit.Test;  
    5.   
    6.   
    7. import static org.junit.Assert.assertTrue;  
    8. /* 
    9.  *  
    10.  * 逻辑操作类 
    11.  * 
    12.  */  
    13. public class OperationTests extends AbstractTest {  
    14.   
    15.   
    16.     public OperationTests() {}  
    17.   
    18.   
    19.     /* 一个简单的加法运算,期望结果为正确的值 */  
    20.     @Test  
    21.     public void twoPlusTwoOperation() {  
    22.   
    23.   
    24.         app.calculatorScreen().addTwoAndTwo();  
    25.         assertTrue(app.calculatorScreen().isResultCorrect("4"));  
    26.   
    27.   
    28.     }  
    29.   
    30.   
    31. }  

    将计算器的例子放在一边,并跳入一个现实世界的例子:

    [java] view plain copy
     
    1. public class ChatTest extends AbstractTest {  
    2.     @Test  
    3.         public void sendMessageAndCheckHistoryTest() {  
    4.   
    5.             login(Credentials.VALID_USER_CREDENTIALS);  
    6.   
    7.              app.mainScreen().startChatWithUser(TEST_USERNAME);  
    8.   
    9.             app.chatScreen().sendChatMessage(TEST_MESSAGE);  
    10.   
    11.             app.chatScreen().navigateToHistoryScreen();  
    12.             assertTrue(app.historyScreen().containsMessage(TEST_MESSAGE));  
    13.   
    14.         }  
    15.   
    16.   
    17.         @Test  
    18.         public void sendAndDeleteMessageThenCheckHistoryTest() {  
    19.   
    20.   
    21.             ...  
    22.   
    23.   
    24.         }         
    25.   
    26.   
    27. }  

    正如你所看到的,当涉及多个屏幕时,这种模式的目的变得清晰,方便起见。我们现在正在浏览我们从未见过的一系列屏幕,但是我们已经可以得到我们测试中发生了什么的一般概念。如果我们看看我们调用的屏幕方法的实现,我们将会更准确地了解发生了什么。事实上,我们可以在没有这样做的情况下收集一些信息是使用PageObject编写测试的好处之一。
    如果UI发生小的变化,我们可能不需要改动我们的测试方法:改动将在我们的屏幕方法之一发生。在这种变化频繁的敏捷环境中,除了测试脚本的强大性外,还特别受欢迎。
    您可以选择自己的屏幕方法的复杂程度。拥有更多,更简单的屏幕方法将导致更长,更详细的测试方法,暴露更多的交互的复杂性。按照这种方法,上述方法看起来更像这样:

    [java] view plain copy
     
    1. @Test  
    2. public void sendMessageAndCheckHistoryTest() {  
    3.   
    4.     login(Credentials.VALID_USER_CREDENTIALS);  
    5.   
    6.     app.mainScreen().navigateToUserSelection();  
    7.   
    8.     app.userSelectionScreen().selectUser(TEST_USERNAME);  
    9.   
    10.     app.userProfileScreen().startChat();  
    11.   
    12.     app.chatScreen().sendChatMessage(TEST_MESSAGE);  
    13.     app.chatScreen().navigateToMainScreen();  
    14.   
    15.     app.mainScreen().navigateToHistoryScreen();  
    16.   
    17.     assertTrue(app.historyScreen().containsMessage(TEST_MESSAGE));  
    18.   
    19.   
    20.   
    21.   
    22. }  

    虽然这种方法显示了屏幕之间的每个过渡,但是它可能很容易成为压倒性的,如在这个例子中:

    [java] view plain copy
     
    1. public class CreateDocumentationWithSuggestionTest extends AbstractTest {  
    2.   
    3.     @Test  
    4.     public void buildNewDocumentationWithSuggestions() {  
    5.   
    6.         app.documentationScreen().navigateToSettings();  
    7.         app.settingsScreen().navigateToSuggestions();  
    8.         app.settingsScreen().activateSuggestions(SUGGESTIONS));  
    9.         app.settingsScreen().navigateToDocumentation();  
    10.         app.documentationScreen().createDocumentation();  
    11.         app.documentationCreationScreen().selectCultivation();  
    12.         app.documentationDetailsScreen().selectFields(TEST_CULTIVATION_1.getFields());  
    13.         app.documentationDetailsScreen().selectConsumables(TEST_CULTIVATION_1.getConsumables());  
    14.         app.documentationDetailsScreen().selectWorkers(TEST_CULTIVATION_1.getWorkers());  
    15.         app.documentationDetailsScreen().sendActivity();  
    16.         app.documentationScreen().createDocumentation();  
    17.         app.documentationCreationScreen().selectCultivation();  
    18.         Assert.assertTrue(app.documentationDetailsScreen().areSuggestedFieldsFilledOut(TEST_CULTIVATION_1));  
    19.   
    20.     }  
    21.     ...  
    22.   
    23. }  

    您应该保持测试方法足够短,以便您能够一目了然地告诉他们做什么,而不用将所有内容都包装到单一屏幕方法中。寻找平衡是编写一个好的,可维护的测试套件的关键。
    总结:
    PageObject前期可能工作量有点多,但是后面都是照葫芦画瓢非常容易维护,所以使用起来性价比还是挺高的,相比直来直去的测试脚本也减少了大量的重复代码

  • 相关阅读:
    1755:菲波那契数列
    1788:Pell数列
    3089:爬楼梯
    7832:最接近的分数
    7649:我家的门牌号
    7216:Minecraft
    7213:垃圾炸弹
    2983:谁是你的潜在朋友
    2723:因子问题
    2722:和数
  • 原文地址:https://www.cnblogs.com/111testing/p/8373335.html
Copyright © 2020-2023  润新知