Di tim saya, kami melakukan pengujian UI lintas platform menggunakan Appium dan Appium Java-Client. Struktur proyek kami saat ini adalah seperti:
mobile
pages
SignInPage
steps
SignInSteps
Langkah-langkahnya “direkatkan” dengan menggunakan Cucuember. SignInPage terlihat seperti ini:
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();
}
}
Kami tidak yakin dalam hal kinerja dan pencarian elemen di mana cara terbaik untuk membuat instance SignInPage. Saat ini kami memiliki metode @Before di SignInSteps kami yang dijalankan sebelum setiap skenario Gherkin dimulai (yang tidak ideal) tetapi ini membantu kami memiliki properti SignInPage di kelas SignInSteps yang digunakan kembali oleh semua langkah.
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
}
Namun saya merasa pendekatan yang lebih bersih adalah dengan membuat SignInPage sebagai variabel lokal di dalam setiap metode langkah di SignInSteps. Apakah ada dampak kinerja dalam pembuatan halaman yang Anda perlukan di setiap langkah?
Selain itu, tidak jelas bagi saya, dengan pendekatan kami saat ini (pendekatan @Before) mengapa sebenarnya ini berfungsi bahkan ketika Anda membuat halaman untuk beberapa langkah yang akan dijalankan nanti (sehingga layar bahkan tidak terlihat pada saat ini) .
Jadi mungkin pertanyaan yang lebih besar adalah bagaimana elemen-elemennya dicari? Apakah saat memanggil PageFactory.initElements(new AppiumFieldDecorator(driver, 15, TimeUnit.SECONDS), this); atau ketika benar-benar mengakses properti beranotasi (yang merupakan semacam pendekatan inisialisasi malas yang menurut pengetahuan saya tidak dimiliki Java, kecuali pemahaman saya tentang anotasi Java salah).
Maaf postingannya panjang, tapi ini beberapa hal yang ingin saya pahami secara menyeluruh. Jadi bantuan apa pun sangat dihargai.
Terima kasih!