Appium PageObject - เมื่อใด / จะสร้างอินสแตนซ์ของหน้าได้ที่ไหน?

ในทีมของฉัน เรากำลังทำการทดสอบ UI ข้ามแพลตฟอร์มโดยใช้ Appium และ Appium Java-Client โครงสร้างปัจจุบันของโครงการของเรามีดังนี้:

mobile
   pages
     SignInPage
   steps
     SignInSteps

ขั้นตอนจะ "ติดกาว" เข้าด้วยกันโดยใช้แตงกวา SignInPage มีลักษณะดังนี้:

public class SignInPage {

    public SignInPage(AppiumDriver driver) {
        PageFactory.initElements(new AppiumFieldDecorator(driver, 15, TimeUnit.SECONDS), this);
    }

    // region Identifiers
    final String IOS_USERNAME_FIELD = "SignInUsernameField";
    final String ANDROID_USERNAME_FIELD = "new UiSelector().resourceIdMatches(\".*id/username.*\")";
    final String IOS_PASSWORD_FIELD = "SignInPasswordField";
    final String ANDROID_PASSWORD_FIELD = "new UiSelector().resourceIdMatches(\".*id/password_editText.*\")";
    final String IOS_SIGN_IN_BUTTON = "SignInButton";
    final String ANDROID_SIGN_IN_BUTTON = "new UiSelector().resourceIdMatches(\".*id/signInButton.*\")";
    // endregion

    @iOSFindBy(accessibility = IOS_USERNAME_FIELD)
    @AndroidFindBy(uiAutomator = ANDROID_USERNAME_FIELD)
    private MobileElement usernameField;

    @iOSFindBy(accessibility = IOS_PASSWORD_FIELD)
    @AndroidFindBy(uiAutomator = ANDROID_PASSWORD_FIELD)
    private MobileElement passwordField;

    @iOSFindBy(accessibility = IOS_SIGN_IN_BUTTON)
    @AndroidFindBy(uiAutomator = ANDROID_SIGN_IN_BUTTON)
    private MobileElement signInButton;

    public MobileElement getUsernameField() {
        return usernameField;
    }

    public MobileElement getPasswordField() {
        return passwordField;
    }

    public MobileElement getSignInButton() {
        return signInButton;
    }

    public void tapUsernameField() {
        getUsernameField().click();
    }

    public void tapSignInButton() {
        getSignInButton().click();
    }

    public void clearUsernameEditText() {
        getUsernameField().clear();
    }
}

เราไม่แน่ใจในแง่ของประสิทธิภาพและการค้นหาองค์ประกอบที่ใดดีที่สุดในการสร้างอินสแตนซ์ของ SignInPage ขณะนี้เรามีเมธอด @Before ใน SignInSteps ของเราที่ดำเนินการก่อนที่สถานการณ์ Gherkin แต่ละสถานการณ์จะเริ่มต้น (ซึ่งไม่เหมาะ) แต่มันช่วยให้เรามีคุณสมบัติ SignInPage ในคลาส SignInSteps ที่ถูกนำมาใช้ซ้ำในทุกขั้นตอน

public class SignInSteps {

    private SignInPage signInPage;
    AppiumDriver driver;

    @Before()
    public void setUp() throws MalformedURLException {
        driver = TestBase.getInstance().getDriver();
        signInPage = new SignInPage(driver);
    }

    @Given("I fill in the username and password")
    public void fill_username_and_password() throws Throwable {
        signInPage.tapUsernameField();
        signInPage.clearUsernameEditText();
        fillEditText(signInPage.getUsernameField(), PropertiesManager.getInstance().getValueForKey(Constants.SIGN_IN_USERNAME));
        fillEditText(signInPage.getPasswordField(), PropertiesManager.getInstance().getValueForKey(Constants.SIGN_IN_PASSWORD));
    }
  // Other sign in steps below
}

อย่างไรก็ตาม ฉันรู้สึกว่าแนวทางที่สะอาดกว่าคือการสร้าง SignInPage เป็นตัวแปรภายในเครื่องในแต่ละขั้นตอนใน SignInSteps มีผลกระทบด้านประสิทธิภาพในการสร้างเพจที่คุณต้องการในแต่ละขั้นตอนหรือไม่?

นอกจากนี้ ยังไม่ชัดเจนสำหรับฉันด้วยแนวทางปัจจุบันของเรา (แนวทาง @Before) เหตุใดจึงใช้งานได้จริงแม้ว่าคุณจะสร้างเพจสำหรับบางขั้นตอนที่จะดำเนินการในภายหลัง (ดังนั้นหน้าจอจึงไม่สามารถมองเห็นได้ ณ จุดนี้) .

บางทีคำถามที่ใหญ่กว่าก็คือองค์ประกอบต่างๆ จะถูกค้นหาอย่างไร เกิดขึ้นเมื่อเรียก PageFactory.initElements(appiumFieldDecorator ใหม่ (ไดรเวอร์, 15, TimeUnit.SECONDS) สิ่งนี้); หรือเมื่อเข้าถึงคุณสมบัติที่มีคำอธิบายประกอบจริง (ซึ่งอาจเป็นวิธีการเริ่มต้นแบบขี้เกียจบางประเภทที่จากความรู้ของฉัน Java ไม่มี เว้นแต่ความเข้าใจเกี่ยวกับคำอธิบายประกอบ Java ของฉันผิด)

ขออภัยสำหรับการโพสต์ที่ยาว แต่นี่คือบางสิ่งที่ฉันอยากจะเข้าใจอย่างถี่ถ้วน ดังนั้นความช่วยเหลือใด ๆ จึงได้รับการชื่นชมอย่างมาก

ขอบคุณ!


person Cosmin    schedule 28.11.2016    source แหล่งที่มา


คำตอบ (1)


ฉันค้นคว้าเพิ่มเติม (แก้ไขจุดบกพร่อง) และพบคำตอบแล้ว:

เมื่อคุณเรียก PageFactory.initElements(new AppiumFieldDecorator(driver, 15, TimeUnit.SECONDS), this); คุณสมบัติที่มีคำอธิบายประกอบจากเพจจะถูกตั้งค่า (ตกแต่ง) ผ่านการสะท้อน (ดู AppiumFieldDecorator) ด้วยพร็อกซี (ElementInterceptor) ที่ล้อม MobileElement แต่ละครั้งที่คุณเรียกเมธอดบนคุณสมบัติที่มีคำอธิบายประกอบ คุณจะเรียกพร็อกซีที่ค้นหาองค์ประกอบและส่งต่อการเรียกเมธอด ไม่มีแคชอยู่ระหว่างนั้น (ตรงข้ามกับ WidgetInterceptor ซึ่งฉันยังไม่รู้ว่ามันถูกใช้ที่ไหน)

ดังนั้นในกรณีของฉัน การสร้างเพจเพียงครั้งเดียวหรือในแต่ละขั้นตอนไม่ได้สร้างความแตกต่างจริงๆ เนื่องจากการค้นหาองค์ประกอบจะดำเนินการทุกครั้งที่คุณโต้ตอบกับเพจ (ซึ่งฉันเดาว่ามันดี แต่อาจมีผลกระทบต่อประสิทธิภาพด้วย)

ฉันได้แนบภาพหน้าจอบางส่วนด้านล่างด้วย:

Stacktrace เมื่อคุณเรียก PageFactory.initElements(appiumFieldDecorator ใหม่ (ไดรเวอร์, 15, TimeUnit.SECONDS) สิ่งนี้);

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

Stacktrace เมื่อคุณเรียก click บนองค์ประกอบ

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

หวังว่านี่จะช่วยให้ผู้อื่นเข้าใจวิธีการทำงานของเครื่องมือได้เช่นกัน

person Cosmin    schedule 04.12.2016