В моей команде мы проводим кроссплатформенное тестирование пользовательского интерфейса с использованием Appium и Appium Java-Client. Текущая структура нашего проекта выглядит примерно так:
mobile
pages
SignInPage
steps
SignInSteps
Ступени «склеиваются» с помощью Cucuember. 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 неверно).
Извините за длинный пост, но это некоторые вещи, которые я хочу понять полностью. Так что любая помощь высоко ценится.
Благодарю вас!