Dans mon équipe, nous effectuons des tests d'interface utilisateur multi-plateforme en utilisant Appium et le client Java Appium. La structure actuelle de notre projet est quelque chose comme:Appium PageObject - Quand/Où instancier la page?
mobile
pages
SignInPage
steps
SignInSteps
Les étapes sont « collés » ensemble à l'aide Cucuember. SignInPage ressemble à quelque chose comme ceci:
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();
}
}
Nous ne sommes pas sûrs en termes de performance et des éléments recherche où est-il préférable de créer une instance de la SignInPage. Actuellement, nous avons une méthode @Before dans nos SignInSteps qui est exécutée avant le début de chaque scénario Gherkin (ce qui n'est pas idéal) mais cela nous aide à avoir une propriété SignInPage dans la classe SignInSteps qui est réutilisée par toutes les étapes.
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
}
Cependant, je pense qu'une approche plus propre serait de créer la SignInPage comme une variable locale dans chaque méthode étape SignInSteps. Y a-t-il un impact sur les performances dans la création des pages dont vous avez besoin à chaque étape? De plus, avec notre approche actuelle (l'approche @Before), je ne comprends pas pourquoi exactement cela fonctionne même lorsque vous créez une page pour certaines étapes qui seront exécutées plus tard (donc l'écran n'est même pas visible) À ce point).
Alors peut-être la plus grande question serait de savoir comment les éléments sont recherchés? Est-ce lors de l'appel de PageFactory.initElements (nouveau AppiumFieldDecorator (pilote, 15, TimeUnit.SECONDS), this); ou en accédant réellement aux propriétés annotées (ce qui serait une sorte d'approche d'initialisation paresseuse que, à ma connaissance, Java ne possède pas, à moins que ma compréhension des annotations Java ne soit fausse).
Désolé pour le poste long, mais ce sont des choses que je veux bien comprendre. Donc, toute aide est très appréciée.
Merci!