Step Library con Playwright
Las Step Library (bibliotecas de pasos) son el puente entre tus pruebas y los Page Object. Proporcionan las capacidades de reportes enriquecidos de Serenity a traves de anotaciones @Step mientras mantienen tus pruebas limpias y legibles.
La arquitectura de tres capas
Clase de prueba
│ Usa @Steps para inyectar Step Library
│ Se enfoca en escenarios de negocio
▼
Step Library
│ Los metodos @Step aparecen en reportes
│ Orquesta acciones del Page Object
▼
Page Object
Encapsula localizadores
Maneja interacciones de pagina
Creacion de Step Library
Estructura basica
public class ShoppingCartSteps {
private ShoppingCartPage cartPage;
// Inicializar Page Object cuando sea necesario
private void ensurePageObject(Page page) {
if (cartPage == null) {
cartPage = new ShoppingCartPage(page);
}
}
@Step("Add product '{1}' to cart")
public void addProductToCart(Page page, String productName) {
ensurePageObject(page);
cartPage.addProduct(productName);
}
@Step("Verify cart contains {1} items")
public void verifyCartItemCount(Page page, int expectedCount) {
ensurePageObject(page);
assertThat(cartPage.getItemCount())
.as("Cart item count")
.isEqualTo(expectedCount);
}
@Step("Proceed to checkout")
public void proceedToCheckout(Page page) {
ensurePageObject(page);
cartPage.clickCheckout();
}
}
Uso de Step Library en pruebas
Inyecta las Step Library usando la anotacion @Steps:
@ExtendWith(SerenityJUnit5Extension.class)
class ShoppingTest {
@Steps
ShoppingCartSteps cart;
@Steps
ProductSteps products;
@Steps
CheckoutSteps checkout;
private Page page;
@Test
void shouldCompleteAPurchase() {
products.browseCategory(page, "Electronics");
products.selectProduct(page, "Laptop Pro");
cart.addProductToCart(page, "Laptop Pro");
cart.verifyCartItemCount(page, 1);
cart.proceedToCheckout(page);
checkout.completeOrder(page);
}
}
La anotacion @Step
Descripciones de paso
Usa marcadores de posicion de parametros en las descripciones de pasos:
@Step("Search for '{1}'")
public void searchFor(Page page, String term) { ... }
@Step("Add {1} units of '{2}' to cart")
public void addToCart(Page page, int quantity, String product) { ... }
@Step("Verify total is ${1}")
public void verifyTotal(Page page, BigDecimal expectedTotal) { ... }
Los indices de parametros comienzan en cero: {0} es el primer parametro, {1} es el segundo, etc.
Pasos anidados
Los pasos pueden llamar a otros pasos para reportes jerarquicos:
@Step("Complete checkout with credit card")
public void completeCheckoutWithCreditCard(Page page, CreditCard card) {
enterBillingAddress(page, card.getBillingAddress());
enterCardDetails(page, card);
submitPayment(page);
}
@Step("Enter billing address")
public void enterBillingAddress(Page page, Address address) {
checkoutPage.enterAddress(address);
}
@Step("Enter card details")
public void enterCardDetails(Page page, CreditCard card) {
checkoutPage.enterCardNumber(card.getNumber());
checkoutPage.enterExpiry(card.getExpiry());
checkoutPage.enterCvv(card.getCvv());
}
@Step("Submit payment")
public void submitPayment(Page page) {
checkoutPage.clickPay();
}
Pasos conscientes de la pagina
Para firmas de paso mas limpias, usa PlaywrightSerenity.getCurrentPage():
public class NavigationSteps {
@Step("Navigate to {0}")
public void navigateTo(String url) {
Page page = PlaywrightSerenity.getCurrentPage();
page.navigate(url);
}
@Step("Refresh the page")
public void refreshPage() {
PlaywrightSerenity.getCurrentPage().reload();
}
@Step("Go back")
public void goBack() {
PlaywrightSerenity.getCurrentPage().goBack();
}
}
Uso en pruebas:
@Test
void shouldNavigateBetweenPages() {
// No es necesario pasar el parametro page
navigation.navigateTo("https://example.com");
navigation.refreshPage();
navigation.goBack();
}
Cuando uses getCurrentPage(), asegurate de haber registrado la pagina con PlaywrightSerenity.registerPage(page) antes de llamar a cualquier paso.
Captura de pantallas
Capturas automaticas
Las capturas de pantalla se capturan automaticamente despues de que cada metodo @Step se completa. Esto es manejado por el PlaywrightStepListener.
Capturas manuales
Dispara capturas de pantalla adicionales en puntos especificos:
@Step("Capture current state")
public void captureCurrentState(Page page) {
// Realizar algunas acciones
performComplexAction(page);
// Capturar una pantalla manualmente
PlaywrightSerenity.takeScreenshot();
// Continuar con mas acciones
performAnotherAction(page);
}
Organizacion de Step Library
Por area de funcionalidad
steps/
├── authentication/
│ ├── LoginSteps.java
│ └── RegistrationSteps.java
├── shopping/
│ ├── ProductSteps.java
│ ├── CartSteps.java
│ └── CheckoutSteps.java
└── account/
├── ProfileSteps.java
└── OrderHistorySteps.java
Por recorrido del usuario
steps/
├── BuyerSteps.java // Todos los pasos para el perfil comprador
├── SellerSteps.java // Todos los pasos para el perfil vendedor
└── AdminSteps.java // Todos los pasos para un administrador
Mejores practicas
1. Mantener los pasos enfocados
Cada paso debe representar una accion logica del usuario:
// ❌ Mal: Demasiadas cosas en un paso
@Step("Login and add product to cart")
public void loginAndAddToCart(Page page, User user, String product) {
// Demasiado sucediendo aqui
}
// ✅ Bien: Pasos enfocados y de proposito unico
@Step("Login as {1}")
public void login(Page page, User user) { ... }
@Step("Add '{1}' to cart")
public void addToCart(Page page, String product) { ... }
2. Usar lenguaje de negocio
Los pasos deben leerse como lenguaje natural:
// ❌ Mal: Lenguaje tecnico
@Step("Click submit button")
@Step("Fill input field with value")
// ✅ Bien: Lenguaje de negocio
@Step("Submit the order")
@Step("Enter shipping address")
3. Manejar el estado cuidadosamente
Se consciente del estado entre llamadas a pasos:
public class AccountSteps {
private AccountPage accountPage;
private User currentUser; // Rastrear estado cuando sea necesario
@Step("Login as {1}")
public void loginAs(Page page, User user) {
// Guardar para pasos posteriores
this.currentUser = user;
loginPage.loginAs(user.getEmail(), user.getPassword());
}
@Step("Verify welcome message shows user's name")
public void verifyWelcomeMessage(Page page) {
assertThat(accountPage.getWelcomeMessage())
.contains(currentUser.getFirstName());
}
}
4. Hacer aserciones claras
Incluye aserciones descriptivas en pasos de verificacion:
@Step("Verify order total is ${1}")
public void verifyOrderTotal(Page page, BigDecimal expectedTotal) {
BigDecimal actualTotal = checkoutPage.getOrderTotal();
assertThat(actualTotal)
.as("Order total")
.isEqualByComparingTo(expectedTotal);
}
@Step("Verify error message is displayed")
public void verifyErrorMessageDisplayed(Page page, String expectedMessage) {
assertThat(errorPage.getMessage())
.as("Error message")
.containsIgnoringCase(expectedMessage);
}
5. Componer pasos de nivel superior
Construye flujos de trabajo complejos a partir de pasos mas simples:
@Step("Complete guest checkout")
public void completeGuestCheckout(Page page, Address address, CreditCard card) {
enterShippingAddress(page, address);
selectShippingMethod(page, "Standard");
enterPaymentDetails(page, card);
confirmOrder(page);
}
Esto crea un reporte jerarquico que muestra tanto el paso de alto nivel como sus partes constituyentes.