Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Introducción
Un patrón es una solución general reutilizable para un problema común en un contexto dado. En
ingeniería de software, un patrón es una técnica de diseño de software que se utiliza para dar
solución a una clase de problema concreto.
¿Qué no es un patrón?
• Prescriptivo, es decir, un patrón no establece como se deben hacer las cosas, este puede
ser mutable ante las condiciones del problema y la experticia del desarrollador.
• Un procedimiento paso a paso. Un patrón no es una receta que se deba seguir
estrictamente al pie de la letra.
• Una solución terminada que puede simplemente adaptarse al problema que se tiene. Un
patrón no siempre es aplicable, se debe analizar, si el patrón que se pretende aplicar
genera valor a mi desarrollo.
¿Dónde utilizarlos?
Ventajas
Desventajas
Tipos de patrones
• Según su propósito
- Creacionales
- De comportamiento
• Según su alcance
- De clase
- De objeto
Patron Builder
Ventajas
• Reduce el acoplamiento.
• Se independiza el código de construcción de la representación.
• Permite un mayor control en el proceso de creación del objeto.
Diagrama de clases
En la figura 1 se puede observar el diagrama de clases que se utiliza para el patrón builder.
A continuación, se da una breve explicación de la función que cumple cada uno de sus
elementos:
• Builder:
Interfaz abstracta para crear productos.
• Concrete Builder:
- Implementación del Builder
- Construye y reúne las partes necesarias para construir los productos
• Director:
Construye un objeto usando el patrón Builder.
• Producto:
El objeto complejo bajo construcción
En la figura 1 se puede observar como debería ser el modelo para implementar el patrón. Dado
que no es necesario totalmente pegarse a la teoría del patrón nosotros los modelaremos de la
siguiente manera:
Sin embargo, en un proyecto se puede tener varios objetos builder, y se puede garantizar que
como mínimo todos tendrán una función build, por ende, se realizará una refactorización del
código para obligar a todas las clases builder a que como mínimo deben implementar dicho
método. Para dicha refactorización, como primer paso, se creará una interfaz con un método
build como se observa a continuación:
T build();
Luego se debe refactorizar la clase que implementa el build, en este caso la clase TaskBuilder,
como se observa a continuación:
public class TaskBuilder implements Builder<Task> {
@Override
public Task build() {
return new Task(id,summary, description,done, dueDate);
}
}
Screen Play
Screenplay se presenta como una mejora al patrón Page Object principalmente porque usando
page object, el automatizador construye código basado en la interfaz de usuario y no en las
interacciones que tiene el usuario con el sistema. Este patrón, centrado en el usuario y
orientado a tareas es la aplicación de los principios S.O.L.I.D en los proyectos de
automatización, especialmente el principio de responsabilidad única y abierto-cerrado.
Este patrón habilita al automatizador a diseñar dirigido en el dominio (DDD), lo que se espera se
traduzca en un mayor acercamiento al negocio dado que siempre se habla y desarrolla en
términos de negocio (lenguaje ubiquo). Para mayor información acerca de DDD puede dirigirse
al libro de Erick Evans: Domain-Driven Design: Tackling Complexity in the Heart of Software o al
siguiente enlace donde se resume este enfoque.
Screenplay es “framework agnostic”, eso quiere decir que no tiene dependencias con la
tecnología, procesos o sistemas, sin embargo, para Bancolombia será aplicado
usando Serenity BDD.
Usar screenplay obliga a pensar en términos de roles, objetivos y acciones para lograr construir
software limpio, con buenas prácticas y que cumpla con los requisitos no funcionales de
usabilidad y mantenibilidad mínimamente. Aquello que se automatiza está en términos del
proceso de negocio y no en cómo llegar a el (clicks y selects). El modelo se presenta en la figura
3:
Figura 3. Modelo conceptual de screenplay
¿Cómo leer ese modelo? : Un usuario (DOÑA CLARA), habilitado para abrir el navegador ejecuta
una serie de tareas (procesos de negocio como transferir saldo) a través de una serie de acciones
directamente relacionadas con la aplicación (como ingresando a la aplicación, consultando el
saldo, ingresando la cuenta destino y el valor a transferir) y realiza un conjunto de preguntas
acerca del estado de esa aplicación (como consultar que se haya realizado el débito a su
cuenta)
A nivel de código fuente, tomando el ejemplo de la figura 2, se tiene que siempre que se aplique
el patrón se logrará tener un código legible en términos de negocio y no de cómo funciona la
aplicación a través de clics. A esto se le llama “Layers of abstraction”.
Figura 6. Patrón screenplay aplicado
Capas de la arquitectura:
• Features:
Son las narrativas o .feature que equivalen a los escenarios de cucumber diseñados
aplicando BDD. Esos archivos son nombrados en minúscula, separados por “_” y pueden
contener uno o más escenarios dependiendo del caso de negocio de
prueba. Ejm: filtering_client_bank_accounts.feature
Se espera que los escenarios sean especificados usando lenguaje Gherkin y que estén
dados en términos de lo que el usuario espera que pase más no del cómo debe hacerlo.
Es decir, escribir los escenarios como un proceso de negocio de alto nivel, no en términos
de clicks y selects. En la figura 8 se muestra un ejemplo aclaratorio.
▪ A BIT OF UCD FOR BDD & ATDD: GOALS -> TASKS -> ACTIONS
▪ Browser Automation - Serenity
▪ Serenity with Cucumber
Algo muy importante y un caso muy frecuente es el de reuso de escenarios, para esto
se propone no reusar a nivel de narrativas sino de tareas. Para hacer una mayor
aclaración por favor diríjase a la siguiente documentación:
• Step Definitions:
Son clases que mapean cada línea de los escenarios definidos en lenguaje Gherkin a
métodos java. Por cuestiones de legibilidad y mantenibilidad se aconseja que vayan
nombrados de la misma manera en la que se nombraron los runner
agregando StepDefinitions al
final. Ejm: FilteringClientBankAccountsStepDefinitions.java
Cuando una tarea es compuesta por otras tareas o por acciones, en el reporte, ese paso
a paso se verá reflejado.
Figura 12. Los reportes muestran las relaciones entre tareas y acciones.
• Interactions:
Una interacción representa una acción directa del usuario con la interfaz como ingresar
datos en campos o dar clics en botones. Serenity screenplay trae por defecto muchas
interacciones sobre la interfaz, por tanto, no siempre es necesario crear nuevas
interacciones. Un ejemplo de una interacción se representa en la figura 13:
• Questions:
Es la capa donde se especifica el assert de las pruebas. Donde se verifican los resultados
de las operaciones realizadas en las capas anteriores. Serenity usa una librería que se
llama Hamcrest para la construcción de assertions fluidos, esta librería trae muchos por
defecto, en caso de que haya un assertion que sea muy específico del negocio entonces
se crearía en la capa questions. Un ejemplo se presenta en la figura 14:
Figura 15. Clase que servirá como Factory para crear Questions de objetos de negocio llamados Items.
Figura 16. Uso del question.
• User interface:
Son las clases que mapean los componentes de una interfaz de usuario. Sólo deben
realizar ese mapeo, no tienen comportamiento. Se nombran basados en el contenedor
de lo que se está mapeando en mayúscula separado por guión bajo. Ejemplo:
• Integration:
Una capa opcional que será creada a criterio de cada equipo en caso de que hayan
integraciones a otros subsistemas. Para conocer acerca del funcionamiento de la misma
y un ejemplo por favor diríjase al apartado “Recomendaciones para trabajar con
componentes o puntos de control que no tengan interfaz de usuario” de este mismo
documento.
Util:
Una capa opcional que será creada a criterio de cada equipo en caso de que hayan
utilidades que consideren se puedan reusar.
Model:
Una capa donde se encontrarán todos los objetos complejos de negocio, como personas
o cuentas bancarias para ser usados dentro de cualquier capa del proyecto.
Exceptions:
Una capa donde se crearán las excepciones específicas que permitirán la legibilidad de
los reportes cuando las pruebas fallen. La razón de ser de esta capa es porque
normalmente las excepciones del web driver son ambiguas y generalizadas, esto hace
que no entreguen mucha información acerca del estado real de la aplicación en el
momento de la ejecución de los test. Un correcto manejo de las excepciones asegurará
un reporte con errores específicos y bien descritos (no técnicos) para ser presentado
como documentación ante entidades reguladoras.
serenity.compromised.on=org.openqa.selenium.NoSuchFrameException
Dentro de screenplay hay un método llamado orComplainWith() que se puede usar para
manejar excepciones de una manera personalizada y que respete el principio de que las
pruebas deben ser documentación y su uso es como el siguiente:
Para conocer más sobre el manejo de excepciones por favor dirigirse a la siguiente
documentación: Domain-Specific Exceptions with Serenity BDD.
Nota: El nombramiento de objetos, clases, métodos, etc debe obedecer a la
búsqueda del mejoramiento de la legibilidad de los suites de pruebas y por tanto
del reporte. Un recomendación especial es realizar los desarrollos en inglés, ya
que screenplay está desarrollado en inglés y los métodos y clases que de el se
usen aparecerán en inglés en el reporte, esta recomendación se hace con el fin de
estandarizar el lenguaje.
3. Borrar los archivos generados por default en caso de ser necesario. Esto depende mucho
del IDE con el que se esté trabajando.
4. Agregar el stack de tecnologías que se va a utilizar, para este caso se necesita, Junit,
Serenity, Cucumber, ScreenPlay y Hamcrest. Para esto debemos agregar las siguientes
líneas al archivo build.gradle en la raíz del proyecto. (TODO: Buscar como se haría para
maven).
https://github.com/antonioBlandon/GoogleSuiteScreenPlayGradle/blob/master/build.grad
le
I. Se crea el package en las carpetas main y test. En algunos IDE’s será necesario
crear dichas carpetas. La guía para crear el package es el siguiente:
Ej:
co.com.bancolombia.certification.googletranslate
II. Se debe crear un nuevo source folder con la ruta: src/test/resources, y dentro de
este la capa features representada como paquete.
III. Las capas Tasks, Interactions, Questions, User Interface y las transversales (Utils,
Model y Exception) van en la carpeta principal, main. Por lo tanto se deben crear
dichos paquetes en esta ruta.
IV. Las capas Runners y Step Definitions van en la carpeta test. Por lo tanto se deben
crear dichos paquetes en esta ruta.
8. Se agregan las etiquetas necesarias para ejecutar los tests en la clase YoutubeRunner
(dichas etiquetas se deben agregar antes de la definición de la clase), que son las
siguientes:
@RunWith(CucumberWithSerenity.class)
@CucumberOptions(
features = "src/test/resources/features/google_translate.feature",
glue = "co.com.bancolombia.certification.googlesuite.stepdefinitions",
snippets = SnippetType.CAMELCASE
)
10. Se revisa la consola para ver los resultados de correr YoutubeRunner como Junit Test.
De la consola podemos obtener nuestro esqueleto que se debe agregar a la clase
YoutubeStepDefinitions, la cual, se debe crear en el paquete stepdefinitions.
https://chromedriver.storage.googleapis.com/index.html?path=2.40/
En dicho enlace hay varias opciones para descargar y dependerá de la máquina donde
se vayan a realizar las pruebas la opción que se deba seleccionar. El driver que se va a
utilizar es el de navegador de google chrome, pero el framework de Serenity soporta otros
navegadores como Firefox e internet explorer. (TODO: Buscar como se hace con los otros
navegadores).
12. Agregar e instanciar el driver descargado. El driver se debe agregar en la raíz del proyecto
y su instancia se realiza en la clase YoutubeStepDefinitions y se hace de la siguiente
manera:
@Managed(driver = "chrome")
private WebDriver herBrowser;
14. Se crea la tarea para abrir el navegador, la cual, consta de los siguientes pasos:
i. Se crea una clase que represente la acción que se desea realizar, en este caso,
abrir el navegador, por lo tanto la clase se nombra como OpenTheBrowser y se
debe implementar a partir de la interfaz Task para que se reconozca como una
tarea.
ii. Se realiza una configuración previa del ambiente, indicando que el actor puede
abrir un navegador desde la clase YoutubeStepDefinitions como se observa a
continuación.
@Managed(driver = "chrome")
private WebDriver herBrowser;
@Before
public void setUp() {
antonio.can(BrowseTheWeb.with(herBrowser));
}
iii. Se crea la clase que indica la página que va abrir el navegador, en este caso la
página inicial de youtube, por lo tanto se pone un nombre representativo a dicha
clase como YoutubeHomePage. Dicha clase, para respetar la arquitectura del
proyecto, debe alojarse en el paquete userinterfaces.
15. Después de abrir la página, se realiza la tarea de interés (buscar una canción). Para
desarrollar la tarea se deben seguir los siguientes pasos:
iii. En la clase Search debe implementarse los métodos necesarios que solicita la
interfaz Task.
16. Para realizar la tarea se necesita la referencia del botón de buscar y del text area donde
se digita el nombre del video que se busca, para realizar dicho proceso se debe realizar
una inspección de la página y ubicar los id de cada elemento en la medida de lo posible,
en caso contrario, se debe hacer uso de xPath como se hizo para el text area y que se
observa a continuación:
Como se observó el tipo de datos en el que se definen los elementos son los Target que
son de la librería de Screenplay de Serenity.
17.
Cibergrafía
i. Introducción y patrón builder
• http://migranitodejava.blogspot.com/search/label/Introduccion%20a%20Patrones
• http://www.vogella.com/tutorials/DesignPatternBuilder/article.html
• https://www.genbeta.com/desarrollo/bdd-cucumber-y-gherkin-desarrollo-dirigido-
por-comportamiento
• https://www.adictosaltrabajo.com/tutoriales/bdd-con-cucumber/
iii. Xpath
• https://www.guru99.com/xpath-selenium.html
• Beyond Page Objects: Next Generation Test Automation with Serenity and the
Screenplay Pattern