Patron de pruebas automatizadas Screenplay

Antes de hablar del patron Screenplay, me gustaría definir que es un patron de pruebas automatizadas, para aquellos que no se encuentren familiarizados con el concepto, "Un patron de pruebas automatizadas es una manera de resolver algún problema en las pruebas automatizadas y que ha podido resolver con una serie de practicas estandarizadas para muchas personas".

Algo ha tomar en cuenta, un patron no es una serie de pasos como una receta de cocina. En otras palabras un patron se puede adaptar e implementar en nuestro contexto, ayudándonos a resolver algunos de los problemas que pudiéramos tener en especifico.

Exploremos un poco el panorama de las pruebas automatizadas, si actualmente nos encontramos trabajando en proyecto de pruebas automatizadas y estamos construyendo nuestro framework desde cero, la opción mas obvio por muchos es POM (Page Object Model), pero quizá POM no sea la opción mas optima para nuestro actual proyecto.

Recordemos que podemos usar una variedad de patrones al momento de implementa nuestro framework de pruebas automatizadas, mi sugerencia es identificar el que mas haga sentido para nuestro proyecto.

Familiarizándonos con el patron Screenplay

Screenplay trata acerca de escribir nuestras pruebas automatizadas basado en los principios de ingeniería de software tal como son el principio de responsabilidad individual (SRP) y en el principio de abrir y cerrar (Open-Closed).

Screenplay promueve los bueno hábitos de testing y suites de pruebas bien organizadas las cuales son facil de seguir, facil de mantener y facil de extender; habilitando equipos a escribir mas robustos y entendibles pruebas automatizadas. Todo buen patron debe tener buenos hábitos de pruebas, pero en realidad, debemos poner atención en la implementación correcta.

El patron de screenplay ha estado desde el 2007, algunos de los precursores son Antonio Marcano, Andy Palmer, Jan Molak y Jason Ferguson. Existen excelentes explicaciones acerca de los conceptos del patron y los problemas comunes que trata de resolver. Para aquellos familiarizados con el patron de Page Object sabemos que puede ser un poco alto el costo de mantenimiento cuando la solución de automatización crece.

En el patron de screenplay, las pruebas describen como un usuario puede interactuar con la aplicación para alcanzar una meta.

Un usuario interactuando con el sistema es llamado "Actor". Los Actores son la parte central del patron screenplay. Como Screenplay (Guion) los actores tienes uno o mas "Habilidades", como son la habilidad de navegar por la web o realizar una consulta un web service, el "Actor" tambien puede realizar "Tareas", como pueden ser agregar o remover objetos o cosas.

Para interactuar con la aplicaciones, como pueden ser introducir valores en los campos o dar click en botones, los actores necesitan estas interacciones, las cuales son denominadas "Acciones". Los "Actores" pueden hacer "Preguntas" acerca del estado del sistema, como por ejemplo leer un valor de un campo en la pantalla o realizando una consulta a algun web service, de tal forma es como se prueba usando el patron de screenplay.

Implementación del patron Screenplay

Para este ejemplo del patron de Screenplay usaremos Python, para ser específicos un modulo llamada ScreenPy, ScreenPy es una libreria que provee la base para nuestra suite de preubas automatizadas.

pip install screenpy

Para hacer la configuración del patron Screenplay usando ScreenPy, necesitamos ejecutar el siguiente comando dentro de la carpeta de nuestra suite de pruebas:

python -m screenpy-quickstart.py

Este comando creara la jerarquia de archivos por nosotros:

\test_suite_folder
  \features #this is where the actual test files will live
    + feature1.py
    + ...


    \user_interface # files containing locators and/or URLs for each page
    +page1.py
    + ...

Podemos tener otras carpetas por ejemplo "Acciones", "Tareas" o "Habilidades" dependiendo de las capacidades de nuestros "Actores".

Como mencionamos arriba, el patron de Screenplay se centra enteramente en los que nuestros usuarios finales quieren hacer en su sitio, en este caso, nuestros casos de prueba se centraran en lo que nuestros "Actores" pueden hace, como puede ser ganar "Habilidades", realizar "Acciones" y realizar "Preguntas".

from screenpy.actor import Actor, AnActor
from selenium.webdriver import Firefox
from screenpy.abilities import BrowseTheWeb


Anton = AnActor.named("Anton").who_can(BrowseTheWeb.using(Firefox()))

Como podrán observar Anton, nuestro actor esta listo para darnos una actuación de antología con su nueva habilidad "BrowseTheWeb". Ahora necesitamos realizar algunas acciones con su nueva y unica habilidad.

from screenpy import Target
from screenpy.actions import Click

#the string to use as a locator for the element can be a CSS selector or an xpath string
GOOGLE_LINK = Target.the("http://www.google.com").located_by("css select")
Anton.attempts_to(Click.the(GOOGLE_LINK))

Anton esta listo para actuar (En este caso una prueba), recordemos que las pruebas se realizan con "Preguntas":

from screenpy.questions import Text
from screenpy.resolutions import ReadsExactly

GOOGLE_MESSAGE = Target.the("google_message").located_by("div:nth-of-type(1) > .rc .st")
Anton.should_see_the((Text.of(GOOGLE_MESSAGE), ReadsExactly("Test"))

A continuation un ejemplo con estructura de pruebas:

/feature/test_iframe.py

import unittest


from screenpy import AnActor, given, then, when
from screenpy.abilities import BrowseTheWeb
from screenpy.actions import Open, SwitchTo
from screenpy.pacing import act, scene
from screenpy.questions import Text
from screenpy.resolutions import ReadsExactly
from tasks import start


from user_interface.iframe import CONTENT, URLI, IFRAME

class TestFrames(unittest.TestCase):


    def setUp(self):

        self.actor = AnActor.named("Anton").who_can (BrowseTheWeb.using_firefox())

    @act("Perform")
    @scene("SwitchTo")
    def test_switch_to_iframe(self):

      Anton = self.actor

      given(Anton).attempts_to(Open.their_browser_on(URL))
      when(Anton).attempts_to(SwitchTo.the(IFRAME))
      then(Anton).should_see_the(
          (Text.of_the(CONTENT_BOX), ReadsExactly("Your content goes here."))
      )

    def tearDown(self):
        self.actor.exit()

/user_interface/iframe.py

# Locators and URL for the Iframe page.

from screenpy import Target

URLI = "http://the-internet.herokuapp.com/iframe"

IFRAME = Target.the("Iframe").located_by("#mce_0_ifr")
CONTENT = Target.the("The content box").located_by("p")

La filosofia de Python, es baterias incluidas, despues de instalar Screenpy las siguientes dependencias seran instaladas tambien: Selenium, Allure's pytest plugin, pytest, and PyOTP.

Si queremos ver algun reporte en Allure, necesitaremos agregar "--alluredir allure_report", y despues generar los reportes de Allure, "allure serve allure_report" y listo, no necesitamos otra configuración extra (Solo como detalle Allure debe estar disponible localmente https://tinyurl.com/y2rv2ebp).

Si necesitan mas información pueden encontrar ejemplos en el siguiente repo.

Conclusion

El patron de Screnplay es una excelente alternativa y pueden mejorar nuestras soluciones de pruebas automatizadas. Cada proyecto es diferente y a veces necesitamos crear soluciones que puedan ser sostenibles. Les recomiendo este patron si se acopla a sus necesidades especificas. Este patron de Screenplay puede sustituir al modelo Page Object o incluso como complemento.

Entiendo que al principio puede ser un gran reto la implementación, pero, una vez que que vemos los beneficios en cuanto reusabilidad y escalabilidad, puede llegar a ser de gran ayuda a nuestra base de conocimientos. Por ultimo si estan usando el patron de Screenplay con Javascript (Aparte de Serenity), compartan que modulo o componente es el de su elección.

Por ultimo los principios de SOLID pueden ayudar a evitar que su solución de pruebas automatizadas tenga fallas.

Felices Pruebas!

References

Selenium Design Patterns and Best Practices, Dima Kovalenko

26