Invocar un actor en cualquier parte de la automatización con serenityBDD
Buenas lectores.
Alguna vez han necesitado invocar el actor en algún punto de la automatización que no sea en los steps? por ejemplo:
WebElement element = MAP_ROUTE.of(MAP_ROUTE_NAME_MAP).resolveFor(currentActor()).getElement();
Como pueden observar necesitemos resolver un target pero resulta que en la clase o método no recibimos ningún actor.
Existen diferentes formas de abordar el problema, de momento para limitar a lo más común voy a citar 3 ejemplos:
1. Recibir el Actor en el método:
Con esto solucionamos directamente nuestro problema y sin mayores contratiempos
public WebElement traerMapa (Actor actor){
return MAP_ROUTE.of(MAP_ROUTE_NAME_MAP).resolveFor(actor).getElement();
}
El problema es que no es una buena práctica, con solo pensar que ya se vuelve un parámetro de entrada ya sabemos como pinta la cosa.
2. Recibir el Actor por almacenamiento:
Si ya has visto mi blog encontraras muy familiar la siguiente manera de resolver el problema
En el step almacenamos el actor en sesión:
Serenity.setSessionVariable("Actor").to("Jadcode");
Luego en el método lo extraemos:
public WebElement traerMapa (){
Actor actor = Serenity.sessionVariableCalled("Actor");
return MAP_ROUTE.of(MAP_ROUTE_NAME_MAP).resolveFor(actor).getElement();
}
Como pueden apreciar ya no ingresa el usuario como parámetro evitando así malas prácticas pero resulta que al almacenar ese valor en una variable de sesión estamos aumentando la complejidad del código y por ende volvemos a caer en una mala práctica. Si, de nuevo...
3. Recibir el Actor directamente desde Serenity:
Como buena práctica y siguiendo con el patrón screenplay, la forma de solucionar este dilema es invocando al actor en escena de la siguiente manera:
import net.serenitybdd.screenplay.actors.OnStage;
import net.serenitybdd.screenplay.Actor;
Actor actor = OnStage.theActorInTheSpotlight();
Finalmente nuestro código quería:
public WebElement traerMapa (){
return MAP_ROUTE.of(MAP_ROUTE_NAME_MAP).resolveFor(OnStage.theActorInTheSpotlight()).getElement();
}
Como se puede apreciar el código queda más limpio y siguiendo los lineamientos del screenplay.
Otra forma obedeciendo el patron screenplay, se vería de la siguiente manera:
El step
@Given("{actor} create the geofence")
public void createGeofence(Actor actor) {
actor.attemptsTo(CreateGeofenceTask.createGeofence());
}
La task
public static Performable createGeofence() {
return Task.where("{0} create geofence",
actor -> {
Actions act = new Actions(BrowseTheWeb.as(actor).getDriver());
act.moveToElement(LocationMapForm.MAP.resolveFor(actor),0,0).click().build().perform();
}
Conclusiones:
Cuando se trabaja SerenityBDD es mejor siempre apuntar a usar screenplay.
Para poder invocar nuestro Actor siempre se debe inicilizar el cast.
El actor invocado es el que actualmente esta en memoria (invocado), recordemos que si le cambias el nombre, ese sería otro actor dentro de la ejecución.
Si estás usando POM, la segunda opción te puede servir, sin embargo existen mas maneras de resolver este problema, pero no está dentro del alcance de esta publicación.
Saludos.
Fuentes:
https://automatizaciondefuncionales.blogspot.com/2023/01/serenitybdd-almacenar-valores-en.html
Comentarios
Publicar un comentario