Transportador - Guía rápida
Este capítulo le brinda una introducción a Transportador, donde aprenderá sobre el origen de este marco de prueba y por qué tiene que elegirlo, el funcionamiento y las limitaciones de esta herramienta.
¿Qué es transportador?
Protractor es un marco de prueba de código abierto de extremo a extremo para aplicaciones Angular y AngularJS. Fue construido por Google sobre WebDriver. También sirve como un reemplazo para el marco de pruebas AngularJS E2E existente llamado "Angular Scenario Runner".
También funciona como un integrador de soluciones que combina tecnologías potentes como NodeJS, Selenium, Jasmine, WebDriver, Cucumber, Mocha, etc. Junto con las pruebas de la aplicación AngularJS, también escribe pruebas de regresión automatizadas para aplicaciones web normales. Nos permite probar nuestra aplicación como un usuario real porque ejecuta la prueba usando un navegador real.
El siguiente diagrama le dará una breve descripción de Transportador -
Observe que en el diagrama anterior, tenemos:
Protractor - Como se discutió anteriormente, es un contenedor sobre WebDriver JS especialmente diseñado para aplicaciones angulares.
Jasmine- Es básicamente un marco de desarrollo basado en el comportamiento para probar el código JavaScript. Podemos escribir las pruebas fácilmente con Jasmine.
WebDriver JS - Es una implementación de enlaces Node JS para selenium 2.0 / WebDriver.
Selenium - Simplemente automatiza el navegador.
Origen
Como se dijo anteriormente, Protractor es un reemplazo del marco de prueba AngularJS E2E existente llamado "Angular Scenario Runner". Básicamente, el origen de Protractor comienza con el final de Scenario Runner. Una pregunta que surge aquí es ¿por qué necesitamos construir un transportador? Para comprender esto, primero debemos verificar sobre su predecesor: Scenario Runner.
Origen del transportador
Julie Ralph, la principal colaboradora del desarrollo de Protractor, tuvo la siguiente experiencia con Angular Scenario Runner en otro proyecto dentro de Google. Esto se convirtió en la motivación para construir Transportador, especialmente para llenar los vacíos:
“Intentamos usar Scenario Runner y descubrimos que realmente no podía hacer las cosas que necesitábamos probar. Necesitábamos probar cosas como iniciar sesión. Su página de inicio de sesión no es una página angular, y el Scenario Runner no pudo lidiar con eso. Y no podía lidiar con cosas como ventanas emergentes y múltiples ventanas, navegar por el historial del navegador, cosas así ".
La mayor ventaja del transportador fue la madurez del proyecto Selenium y resume sus métodos para que pueda usarse fácilmente para proyectos angulares. El diseño de Protractor está construido de tal manera que prueba todas las capas, como la interfaz de usuario web, los servicios de backend, la capa de persistencia, etc. de una aplicación.
¿Por qué transportador?
Como sabemos, casi todas las aplicaciones utilizan JavaScript para el desarrollo. La tarea de los probadores se vuelve difícil cuando JavaScript aumenta de tamaño y se vuelve complejo para las aplicaciones debido al creciente número de aplicaciones en sí. La mayoría de las veces se vuelve muy difícil capturar los elementos web en las aplicaciones AngularJS, utiliza una sintaxis HTML extendida para expresar los componentes de la aplicación web, utilizando JUnit o Selenium WebDriver.
La pregunta aquí es ¿por qué Selenium Web Driver no puede encontrar elementos web de AngularJS? La razón es que las aplicaciones AngularJS tienen algunos atributos HTML extendidos como ng-repetater, ng-controller y ng-model, etc. que no están incluidos en los localizadores de Selenium.
Aquí, la importancia de Protractor surge porque Protractor en la parte superior de Selenium puede manejar y controlar esos elementos HTML extendidos en las aplicaciones web AngularJS. Es por eso que podemos decir que la mayoría de los marcos se enfocan en realizar pruebas unitarias para aplicaciones AngularJS, Protractor solía hacer pruebas de la funcionalidad real de una aplicación.
Trabajo de transportador
Transportador, el marco de prueba, trabaja en conjunto con Selenium para proporcionar una infraestructura de prueba automatizada para simular la interacción de un usuario con una aplicación AngularJS que se ejecuta en un navegador o dispositivo móvil.
El funcionamiento del transportador se puede entender con la ayuda de los siguientes pasos:
Step 1- En el primer paso, necesitamos escribir las pruebas. Se puede hacer con la ayuda de Jazmín o Moca o Pepino.
Step 2- Ahora, necesitamos ejecutar la prueba que se puede hacer con la ayuda de Transportador. También se le llama corredor de prueba.
Step 3 - En este paso, el servidor Selenium ayudará a administrar los navegadores.
Step 4 - Por fin, las API del navegador se invocan con la ayuda de Selenium WebDriver.
Ventajas
Este marco de prueba de código abierto de extremo a extremo ofrece las siguientes ventajas:
Protractor, una herramienta de código abierto, es muy fácil de instalar y configurar.
Funciona bien con el framework Jasmine para crear la prueba.
Admite el desarrollo basado en pruebas (TDD).
Contiene esperas automáticas, lo que significa que no necesitamos agregar explícitamente esperas y suspensiones a nuestra prueba.
Ofrece todas las ventajas de Selenium WebDriver.
Admite pruebas paralelas a través de varios navegadores.
Proporciona el beneficio de la sincronización automática.
Tiene una excelente velocidad de prueba.
Limitaciones
Este marco de prueba de código abierto de un extremo a otro posee las siguientes limitaciones:
No descubre ninguna vertical en la automatización del navegador porque es un contenedor para WebDriver JS.
El conocimiento de JavaScript es esencial para el usuario, ya que solo está disponible para JavaScript.
Solo proporciona pruebas de front-end porque es una herramienta de prueba impulsada por la interfaz de usuario.
Dado que el conocimiento de JavaScript es esencial para trabajar con Transportador, en este capítulo, comprendamos los conceptos de las pruebas de JavaScript en detalle.
Pruebas y automatización de JavaScript
JavaScript es el lenguaje de secuencias de comandos interpretado y escrito dinámicamente más popular, pero la tarea más desafiante es probar el código. Se debe a que, a diferencia de otros lenguajes compilados como JAVA y C ++, no hay pasos de compilación en JavaScript que puedan ayudar al evaluador a detectar errores. Además, las pruebas basadas en navegador requieren mucho tiempo; por lo tanto, existe la necesidad de herramientas que admitan pruebas automatizadas para JavaScript.
Conceptos de pruebas automatizadas
Siempre es una buena práctica escribir la prueba porque mejora el código; el problema con las pruebas manuales es que consume un poco de tiempo y es propenso a errores. El proceso de prueba manual también es bastante aburrido para el programador, ya que necesita repetir el proceso, escribir especificaciones de prueba, cambiar el código y actualizar el navegador varias veces. Además, las pruebas manuales también ralentizan el proceso de desarrollo.
Por las razones anteriores, siempre es útil tener algunas herramientas que puedan automatizar estas pruebas y ayudar a los programadores a deshacerse de estos pasos repetitivos y aburridos. ¿Qué debe hacer un desarrollador para automatizar el proceso de prueba?
Básicamente, un desarrollador puede implementar el conjunto de herramientas en CLI (Command Line Interpreter) o en el IDE de desarrollo (entorno de desarrollo integrado). Luego, estas pruebas se ejecutarán continuamente en un proceso separado, incluso sin la entrada del desarrollador. Las pruebas automatizadas de JavaScript tampoco son nuevas y se han desarrollado muchas herramientas como Karma, Protractor, CasperJS, etc.
Tipos de pruebas para JavaScript
Puede haber diferentes pruebas para diferentes propósitos. Por ejemplo, algunas pruebas se escriben para verificar el comportamiento de funciones en un programa, mientras que otras se escriben para probar el flujo de un módulo o característica. Por lo tanto, tenemos los siguientes dos tipos de pruebas:
Examen de la unidad
La prueba se realiza en la parte comprobable más pequeña del programa llamada unidad. Básicamente, la unidad se prueba de forma aislada sin ningún tipo de dependencia de esa unidad de las otras partes. En el caso de JavaScript, el método o función individual que tiene un comportamiento específico puede ser una unidad de código y estas unidades de código deben probarse de forma aislada.
Una de las ventajas de las pruebas unitarias es que la prueba de las unidades se puede realizar en cualquier orden porque las unidades son independientes entre sí. Otra ventaja de las pruebas unitarias que realmente cuenta es que puede ejecutar la prueba en cualquier momento de la siguiente manera:
- Desde el comienzo del proceso de desarrollo.
- Después de completar el desarrollo de cualquier módulo / función.
- Después de modificar cualquier módulo / función.
- Después de agregar cualquier característica nueva en la aplicación existente.
Para las pruebas unitarias automatizadas de aplicaciones JavaScript, podemos elegir entre muchas herramientas y marcos de prueba como Mocha, Jasmine y QUnit.
Pruebas de extremo a extremo
Puede definirse como la metodología de prueba utilizada para probar si el flujo de la aplicación de principio a fin (de un extremo a otro) está funcionando bien según el diseño.
Las pruebas de extremo a extremo también se denominan pruebas de función / flujo. A diferencia de las pruebas unitarias, las pruebas de un extremo a otro prueban cómo los componentes individuales funcionan juntos como una aplicación. Ésta es la principal diferencia entre las pruebas unitarias y las pruebas de extremo a extremo.
Por ejemplo, supongamos que si tenemos un módulo de registro donde el usuario necesita proporcionar información válida para completar el registro, entonces la prueba E2E para ese módulo en particular seguirá los siguientes pasos para completar la prueba:
- Primero, cargará / compilará el formulario o módulo.
- Ahora, obtendrá el DOM (modelo de objetos de documento) de los elementos del formulario.
- A continuación, active el evento de clic del botón enviar para comprobar si funciona o no.
- Ahora, para fines de validación, recopile el valor de los campos de entrada.
- A continuación, se deben validar los campos de entrada.
- Con fines de prueba, llame a una API falsa para almacenar los datos.
Cada paso da sus propios resultados que se compararán con el conjunto de resultados esperado.
Ahora, la pregunta que surge es, si bien este tipo de E2E o pruebas funcionales también se pueden realizar manualmente, ¿por qué necesitamos automatización para esto? La razón principal es que la automatización facilitará este proceso de prueba. Algunas de las herramientas disponibles que se pueden integrar fácilmente con cualquier aplicación, para tal fin son Selenium, PhantomJS y Protractor.
Herramientas de prueba y marcos
Tenemos varias herramientas de prueba y marcos para pruebas angulares. Las siguientes son algunas de las herramientas y marcos más conocidos:
Karma
Karma, creado por Vojta Jina, es un corredor de pruebas. Originalmente este proyecto se llamó Testacular. No es un marco de prueba, lo que significa que nos brinda la capacidad de ejecutar de manera fácil y automática pruebas unitarias de JavaScript en navegadores reales. Karma se creó para AngularJS porque antes de Karma no existía una herramienta de prueba automatizada para los desarrolladores de JavaScript basados en la web. Por otro lado, con la automatización proporcionada por Karma, los desarrolladores pueden ejecutar un simple comando y determinar si un conjunto de pruebas completo ha pasado o no.
Ventajas de usar Karma
Las siguientes son algunas de las ventajas del uso de Karma en comparación con el proceso manual:
- Automatiza las pruebas en varios navegadores y dispositivos.
- Supervisa los archivos en busca de errores y los corrige.
- Proporciona soporte y documentación en línea.
- Facilita la integración con un servidor de integración continua.
Contras de usar karma
Los siguientes son algunos de los contras de usar Karma:
La principal desventaja de usar Karma es que requiere una herramienta adicional para configurar y mantener.
Si está utilizando el ejecutor de pruebas de Karma con Jasmine, hay menos documentación disponible para encontrar información sobre cómo configurar su CSS en el caso de tener varios identificadores para un elemento.
Jazmín
Jasmine, un marco de desarrollo basado en el comportamiento para probar código JavaScript, se desarrolla en Pivotal Labs. Antes del desarrollo activo del marco Jasmine, Pivotal Labs también desarrolló un marco de prueba unitario similar llamado JsUnit, que tiene un ejecutor de pruebas incorporado. Las pruebas de los navegadores se pueden ejecutar a través de las pruebas de Jasmine al incluir el archivo SpecRunner.html o al usarlo también como un corredor de pruebas de línea de comandos. También se puede usar con o sin Karma.
Ventajas de usar Jasmine
Las siguientes son algunas ventajas de usar Jasmine:
Un marco independiente del navegador, la plataforma y el idioma.
Admite el desarrollo impulsado por pruebas (TDD) junto con el desarrollo impulsado por el comportamiento.
Tiene integración predeterminada con Karma.
Sintaxis fácil de entender.
Proporciona espías de prueba, falsificaciones y funcionalidades de paso que ayudan con las pruebas como funciones adicionales.
Contras de usar Jasmine
La siguiente es una desventaja de usar Jasmine:
El usuario debe devolver las pruebas a medida que cambian porque no hay una función de observación de archivos disponible en Jasmine mientras se ejecuta la prueba.
Moca
Mocha, escrito para aplicaciones Node.js, es un marco de prueba pero también admite pruebas de navegador. Es bastante parecido a Jasmine, pero la principal diferencia entre ellos es que Mocha necesita algún complemento y biblioteca porque no puede ejecutarse de forma independiente como marco de prueba. Por otro lado, Jasmine es independiente. Sin embargo, Mocha es más flexible de usar que Jasmine.
Ventajas de usar Mocha
Las siguientes son algunas ventajas del uso de Mocha:
- Mocha es muy fácil de instalar y configurar.
- Documentación sencilla y fácil de usar.
- Contiene complementos con varios proyectos de nodos.
Contras de usar Mocha
Los siguientes son algunos contras de usar Mocha:
- Necesita módulos separados para afirmaciones, espías, etc.
- También requiere una configuración adicional para usar con Karma.
QUnit
QUint, desarrollado originalmente por John Resig en 2008 como parte de jQuery, es un conjunto de pruebas unitarias de JavaScript potente pero fácil de usar. Se puede utilizar para probar cualquier código JavaScript genérico. Aunque se centra en probar JavaScript en el navegador, es muy conveniente para el desarrollador.
Ventajas de usar QUnit
Las siguientes son algunas ventajas de usar QUnit:
- Fácil de instalar y configurar.
- Documentación sencilla y fácil de usar.
Contras de usar QUnit
La siguiente es una desventaja de usar QUnit:
- Fue desarrollado principalmente para jQuery y, por lo tanto, no es tan bueno para usar con otros marcos.
Selenio
Selenium, desarrollado originalmente por Jason Huggins en 2004 como una herramienta interna en ThoughtWorks, es una herramienta de automatización de pruebas de código abierto. Selenium se define a sí mismo como “Selenium automatiza los navegadores. ¡Eso es!". La automatización de los navegadores significa que los desarrolladores pueden interactuar con los navegadores muy fácilmente.
Ventajas de usar selenio
Las siguientes son algunas ventajas del uso de selenio:
- Contiene un gran conjunto de funciones.
- Admite pruebas distribuidas.
- Tiene soporte SaaS a través de servicios como Sauce Labs.
- Fácil de usar con documentación sencilla y abundantes recursos disponibles.
Contras de usar selenio
Los siguientes son algunos de los contras de usar Selenium:
- Una de las principales desventajas de usar Selenium es que debe ejecutarse como un proceso separado.
- La configuración es un poco engorrosa ya que el desarrollador debe seguir varios pasos.
En los capítulos anteriores, hemos aprendido los conceptos básicos de Transportador. En este capítulo, aprendamos cómo instalarlo y configurarlo.
Prerrequisitos
Necesitamos satisfacer los siguientes requisitos previos antes de instalar Transportador en su computadora:
Node.js
Transportador es un módulo de Node.js, por lo tanto, el requisito previo muy importante es que debemos tener Node.js instalado en nuestra computadora. Vamos a instalar el paquete Protractor usando npm (un administrador de paquetes de JavaScript), que viene con Node.js.
Para instalar Node.js, siga el enlace oficial: https://nodejs.org/en/download/. Después de instalar Node.js, puede verificar la versión de Node.js y npm escribiendo el comandonode --version y npm --version en el símbolo del sistema como se muestra a continuación:
Cromo
Google Chrome, un navegador web creado por Google, se utilizará para ejecutar pruebas de extremo a extremo en Protractor sin la necesidad de un servidor Selenium. Puede descargar Chrome haciendo clic en el enlace -https://www.google.com/chrome/.
Selenium WebDriver para Chrome
Esta herramienta se proporciona con el módulo Protractor npm y nos permite interactuar con aplicaciones web.
Instalación de transportador
Después de instalar Node.js en nuestra computadora, podemos instalar Protractor con la ayuda del siguiente comando:
npm install -g protractor
Una vez que el transportador se ha instalado correctamente, podemos comprobar su versión escribiendo protractor --version comando en el símbolo del sistema como se muestra a continuación -
Instalación de WebDriver para Chrome
Después de instalar Protractor, necesitamos instalar Selenium WebDriver para Chrome. Se puede instalar con la ayuda del siguiente comando:
webdriver-manager update
El comando anterior creará un directorio de Selenium que contiene el controlador de Chrome requerido utilizado en el proyecto.
Confirmación de instalación y configuración
Podemos confirmar la instalación y configuración de Protractor cambiando ligeramente el archivo conf.js proporcionado en el ejemplo después de instalar Protractor. Puede encontrar este archivo conf.js en el directorio raíznode_modules/Protractor/example.
Para esto, primero cree un nuevo archivo llamado testingconfig.js en el mismo directorio, es decir node_modules/Protractor/example.
Ahora, en el archivo conf.js, bajo el parámetro de declaración del archivo fuente, escriba testingconfig.js.
A continuación, guarde y cierre todos los archivos y abra el símbolo del sistema. Ejecute el archivo conf.js como se muestra en la captura de pantalla que se muestra a continuación.
La configuración e instalación de Transportador es exitosa si obtuvo el resultado como se muestra a continuación:
La salida anterior muestra que no hay ninguna especificación porque proporcionamos el archivo vacío en el parámetro de declaración del archivo fuente en el archivo conf.js. Pero a partir de la salida anterior, podemos ver que tanto el transportador como WebDriver se están ejecutando correctamente.
Problemas de instalación y configuración
Al instalar y configurar Transportador y WebDriver, es posible que nos encontremos con los siguientes problemas comunes:
El selenio no se instaló correctamente
Es el problema más común al instalar WebDriver. Este problema surge si no actualiza WebDriver. Tenga en cuenta que debemos actualizar WebDriver, de lo contrario no podríamos hacer referencia a la instalación de Transportador.
No puedo encontrar pruebas
Otro problema común es que después de ejecutar Protractor, muestra que no se pueden encontrar pruebas. Para ello, debemos tener que asegurarnos de que las rutas relativas, nombres de archivo o extensiones sean correctas. También necesitamos escribir el archivo conf.js con mucho cuidado porque comienza con el archivo de configuración.
Como se discutió anteriormente, Protractor es un marco de prueba de código abierto de extremo a extremo para aplicaciones Angular y AngularJS. Es el programa Node.js. Por otro lado, Selenium es un marco de automatización del navegador que incluye Selenium Server, las API de WebDriver y los controladores del navegador WebDriver.
Transportador con selenio
Si hablamos de la conjunción de Transportador y Selenium, Transportador puede trabajar con el servidor Selenium para proporcionar una infraestructura de prueba automatizada. La infraestructura puede simular la interacción del usuario con una aplicación angular que se ejecuta en un navegador o en un dispositivo móvil. La conjunción de transportador y selenio se puede dividir en tres particiones, a saber, prueba, servidor y navegador, como se muestra en el siguiente diagrama:
Procesos de Selenium WebDriver
Como hemos visto en el diagrama anterior, una prueba que utiliza Selenium WebDriver implica los siguientes tres procesos:
- Los guiones de prueba
- El servidor
- El navegador
En esta sección, analicemos la comunicación entre estos tres procesos.
Comunicación entre los scripts de prueba y el servidor
La comunicación entre los dos primeros procesos, los scripts de prueba y el servidor, depende del funcionamiento de Selenium Server. En otras palabras, podemos decir que la forma en que se ejecuta el servidor Selenium le dará forma al proceso de comunicación entre los scripts de prueba y el servidor.
El servidor Selenium puede ejecutarse localmente en nuestra máquina como Selenium Server independiente (selenium-server-standalone.jar) o puede ejecutarse de forma remota a través de un servicio (Sauce Labs). En el caso de un servidor Selenium independiente, habría una comunicación http entre Node.js y el servidor Selenium.
Comunicación entre el servidor y el navegador
Como sabemos, el servidor se encarga de reenviar los comandos al navegador después de interpretarlos desde los scripts de prueba. Es por eso que el servidor y el navegador también requieren un medio de comunicación y aquí la comunicación se realiza con la ayuda deJSON WebDriver Wire Protocol. El navegador ampliado con el controlador del navegador que se utiliza para interpretar los comandos.
El concepto anterior sobre los procesos de Selenium WebDriver y su comunicación se puede entender con la ayuda del siguiente diagrama:
Mientras trabaja con Protractor, el primer proceso, es decir, el script de prueba, se ejecuta usando Node.js, pero antes de realizar cualquier acción en el navegador, enviará un comando adicional para asegurarse de que la aplicación que se está probando esté estabilizada.
Configuración de Selenium Server
Selenium Server actúa como un servidor proxy entre nuestro script de prueba y el controlador del navegador. Básicamente, reenvía el comando de nuestro script de prueba al WebDriver y devuelve las respuestas del WebDriver a nuestro script de prueba. Existen las siguientes opciones para configurar el servidor Selenium que se incluyen enconf.js archivo de secuencia de comandos de prueba -
Servidor Selenium independiente
Si queremos ejecutar el servidor en nuestra máquina local, necesitamos instalar un servidor selenio independiente. El requisito previo para instalar el servidor selenium independiente es JDK (Java Development Kit). Debemos tener JDK instalado en nuestra máquina local. Podemos verificarlo ejecutando el siguiente comando desde la línea de comando:
java -version
Ahora, tenemos la opción de instalar e iniciar Selenium Server manualmente o desde un script de prueba.
Instalación e inicio del servidor Selenium manualmente
Para instalar e iniciar el servidor Selenium manualmente, necesitamos usar la herramienta de línea de comandos WebDriver-Manager que viene con Transportador. Los pasos para instalar e iniciar el servidor Selenium son los siguientes:
Step 1- El primer paso es instalar el servidor Selenium y ChromeDriver. Se puede hacer con la ayuda de ejecutar el siguiente comando:
webdriver-manager update
Step 2- A continuación, necesitamos iniciar el servidor. Se puede hacer con la ayuda de ejecutar el siguiente comando:
webdriver-manager start
Step 3- Por fin necesitamos establecer seleniumAddress en el archivo de configuración a la dirección del servidor en ejecución. La dirección predeterminada seríahttp://localhost:4444/wd/hub.
Iniciar el servidor Selenium desde un script de prueba
Para iniciar el servidor Selenium desde un script de prueba, debemos configurar las siguientes opciones en nuestro archivo de configuración:
Location of jar file - Necesitamos establecer la ubicación del archivo jar para el servidor Selenium independiente en el archivo de configuración configurando seleniumServerJar.
Specifying the port- También necesitamos especificar el puerto que se utilizará para iniciar el servidor Selenium independiente. Se puede especificar en el archivo de configuración configurando seleniumPort. El puerto predeterminado es 4444.
Array of command line options- También necesitamos configurar el conjunto de opciones de línea de comando para pasar al servidor. Se puede especificar en el archivo de configuración configurando seleniumArgs. Si necesita una lista completa de la matriz de comandos, inicie el servidor con el-help bandera.
Trabajar con Remote Selenium Server
Otra opción para ejecutar nuestra prueba es usar el servidor Selenium de forma remota. El requisito previo para usar el servidor de forma remota es que debemos tener una cuenta con un servicio que aloje el servidor. Mientras trabajamos con Transportador, tenemos el soporte integrado para los siguientes servicios que alojan el servidor:
TestObject
Para usar TestObject como el Servidor Selenium remoto, necesitamos establecer testobjectUser, el nombre de usuario de nuestra cuenta TestObject y testobjectKey, la clave API de nuestra cuenta TestObject.
BrowserStack
Para usar BrowserStack como el servidor Selenium remoto, necesitamos configurar el browserstackUser, el nombre de usuario de nuestra cuenta BrowserStack y browserstackKey, la clave API de nuestra cuenta BrowserStack.
Laboratorios de salsa
Para usar Sauce Labs como el servidor Selenium remoto, necesitamos configurar sauceUser, el nombre de usuario de nuestra cuenta de Sauce Labs y SauceKey, la clave API de nuestra cuenta de Sauce Labs.
Kobiton
Para usar Kobiton como Selenium Server remoto, debemos configurar kobitonUser, el nombre de usuario de nuestra cuenta Kobiton y kobitonKey, la clave API de nuestra cuenta Kobiton.
Conexión directa al controlador del navegador sin usar Selenium Server
Una opción más para ejecutar nuestra prueba es conectarse al controlador del navegador directamente sin usar el servidor Selenium. Transportador puede probar directamente, sin el uso de Selenium Server, contra Chrome y Firefox configurando directConnect: true en el archivo de configuración.
Configurar el navegador
Antes de configurar y configurar el navegador, necesitamos saber qué navegadores son compatibles con Protractor. La siguiente es la lista de navegadores compatibles con Protractor:
- ChromeDriver
- FirefoxDriver
- SafariDriver
- IEDriver
- Appium-iOS/Safari
- Appium-Android/Chrome
- Selendroid
- PhantomJS
Para configurar y configurar el navegador, debemos movernos al archivo de configuración de Transportador porque la configuración del navegador se realiza dentro del objeto de capacidades del archivo de configuración.
Configurando Chrome
Para configurar el navegador Chrome, debemos configurar el objeto de capacidades de la siguiente manera
capabilities: {
'browserName': 'chrome'
}
También podemos agregar opciones específicas de Chrome que están anidadas en chromeOptions y su lista completa se puede ver en https://sites.google.com/a/chromium.org/chromedriver/capabilities.
Por ejemplo, si desea agregar un contador de FPS en la esquina superior derecha, puede hacerlo de la siguiente manera en el archivo de configuración:
capabilities: {
'browserName': 'chrome',
'chromeOptions': {
'args': ['show-fps-counter=true']
}
},
Configurando Firefox
Para configurar el navegador Firefox, necesitamos configurar el objeto de capacidades de la siguiente manera:
capabilities: {
'browserName': 'firefox'
}
También podemos agregar opciones específicas de Firefox que están anidadas en el objeto moz: firefoxOptions y su lista completa se puede ver en https://github.com/mozilla/geckodriver#firefox-capabilities.
Por ejemplo, si desea ejecutar su prueba en Firefox en modo seguro, puede hacerlo de la siguiente manera en el archivo de configuración:
capabilities: {
'browserName': 'firefox',
'moz:firefoxOptions': {
'args': ['—safe-mode']
}
},
Configurar otro navegador
Para configurar cualquier otro navegador que no sea Chrome o Firefox, necesitamos instalar un binario separado de https://docs.seleniumhq.org/download/.
Configuración de PhantonJS
En realidad, PhantomJS ya no es compatible debido a sus problemas de bloqueo. En lugar de eso, se recomienda utilizar Chrome sin cabeza o Firefox sin cabeza. Se pueden configurar de la siguiente manera:
Para configurar Chrome sin cabeza, debemos iniciar Chrome con la marca –headless de la siguiente manera:
capabilities: {
'browserName': 'chrome',
'chromeOptions': {
'args': [“--headless”, “--disable-gpu”, “--window-size=800,600”]
}
},
Para configurar Firefox sin cabeza, necesitamos iniciar Firefox con el –headless marcar de la siguiente manera:
capabilities: {
'browserName': 'firefox',
'moz:firefoxOptions': {
'args': [“--headless”]
}
},
Configuración de varios navegadores para realizar pruebas
También podemos realizar pruebas con varios navegadores. Para esto, necesitamos usar la opción de configuración multiCapabilities de la siguiente manera:
multiCapabilities: [{
'browserName': 'chrome'
},{
'browserName': 'firefox'
}]
¿Qué marco?
Dos marcos de prueba BDD (desarrollo impulsado por el comportamiento), Jasmine y Mocha, son compatibles con Protractor. Ambos marcos se basan en JavaScript y Node.js. Estos marcos proporcionan la sintaxis, el informe y el andamiaje necesarios para escribir y administrar las pruebas.
A continuación, vemos cómo podemos instalar varios marcos:
Marco de jazmín
Es el marco de prueba predeterminado para Transportador. Cuando instale Protractor, obtendrá la versión Jasmine 2.x con él. No es necesario que lo instalemos por separado.
Marco moca
Mocha es otro marco de prueba de JavaScript que básicamente se ejecuta en Node.js. Para usar Mocha como nuestro marco de prueba, necesitamos usar la interfaz BDD (desarrollo impulsado por el comportamiento) y las afirmaciones de Chai con Chai As Promised. La instalación se puede realizar con la ayuda de los siguientes comandos:
npm install -g mocha
npm install chai
npm install chai-as-promised
Como puede ver, la opción -g se usa al instalar mocha, es porque hemos instalado Protractor globalmente usando la opción -g. Después de instalarlo, necesitamos requerir y configurar Chai dentro de nuestros archivos de prueba. Se puede hacer de la siguiente manera:
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
var expect = chai.expect;
Después de esto, podemos usar Chai As Promised como tal:
expect(myElement.getText()).to.eventually.equal('some text');
Ahora, necesitamos establecer la propiedad del marco en mocha del archivo de configuración agregando marco: 'mocha'. Las opciones como 'reportero' y 'lento' para mocha se pueden agregar en el archivo de configuración de la siguiente manera:
mochaOpts: {
reporter: "spec", slow: 3000
}
Marco de pepino
Para usar Cucumber como nuestro marco de prueba, necesitamos integrarlo con Transportador con la opción de marco custom. La instalación se puede realizar con la ayuda de los siguientes comandos
npm install -g cucumber
npm install --save-dev protractor-cucumber-framework
Como puede ver, la opción -g se usa al instalar Cucumber, es porque hemos instalado Protractor globalmente, es decir, con la opción -g. A continuación, debemos establecer la propiedad del marco encustom del archivo de configuración agregando framework: 'custom' y frameworkPath: 'Protractor-cucumber-framework' al archivo de configuración llamado cucumberConf.js.
El código de muestra que se muestra a continuación es un archivo cucumberConf.js básico que se puede usar para ejecutar archivos de características de pepino con Transportador -
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
baseUrl: 'https://angularjs.org/',
capabilities: {
browserName:'Firefox'
},
framework: 'custom',
frameworkPath: require.resolve('protractor-cucumber-framework'),
specs: [
'./cucumber/*.feature'
],
// cucumber command line options
cucumberOpts: {
require: ['./cucumber/*.js'],
tags: [],
strict: true,
format: ["pretty"],
'dry-run': false,
compiler: []
},
onPrepare: function () {
browser.manage().window().maximize();
}
};
En este capítulo, entendamos cómo escribir la primera prueba en Transportador.
Archivos requeridos por transportador
Transportador necesita los siguientes dos archivos para ejecutarse:
Archivo de prueba o especificación
Es uno de los archivos importantes para ejecutar Protractor. En este archivo, escribiremos nuestro código de prueba real. El código de prueba se escribe utilizando la sintaxis de nuestro marco de prueba.
Por ejemplo, si estamos usando Jasmine framework, entonces el código de prueba se escribirá utilizando la sintaxis de Jasmine. Este archivo contendrá todos los flujos funcionales y afirmaciones de la prueba.
En palabras simples, podemos decir que este archivo contiene la lógica y los localizadores para interactuar con la aplicación.
Ejemplo
El siguiente es un script simple, TestSpecification.js, que tiene el caso de prueba para navegar a una URL y verificar el título de la página:
//TestSpecification.js
describe('Protractor Demo', function() {
it('to check the page title', function() {
browser.ignoreSynchronization = true;
browser.get('https://www.tutorialspoint.com/tutorialslibrary.htm');
browser.driver.getTitle().then(function(pageTitle) {
expect(pageTitle).toEqual('Free Online Tutorials and Courses');
});
});
});
Explicación del código
El código del archivo de especificación anterior se puede explicar de la siguiente manera:
Navegador
Es la variable global creada por Protractor para manejar todos los comandos del nivel del navegador. Básicamente es un contenedor alrededor de una instancia de WebDriver. browser.get () es un método simple de Selenium que le indicará a Protractor que cargue una página en particular.
describe y it- Ambas son las sintaxis del marco de prueba Jasmine. los’Describe’ se utiliza para contener el flujo de un extremo a otro de nuestro caso de prueba, mientras que ‘it’contiene algunos de los escenarios de prueba. Podemos tener múltiples‘it’ bloques en nuestro programa de casos de prueba.
Expect - Es una afirmación donde comparamos el título de la página web con algunos datos predefinidos.
ignoreSynchronization- Es una etiqueta de navegador que se utiliza cuando intentamos probar sitios web no angulares. Transportador espera trabajar con sitios web angulares solo, pero si queremos trabajar con sitios web no angulares, esta etiqueta debe establecerse en“true”.
Archivo de configuración
Como sugiere el nombre, este archivo proporciona explicaciones para todas las opciones de configuración del transportador. Básicamente le dice a Transportador lo siguiente:
- Dónde encontrar los archivos de prueba o especificaciones
- Que navegador elegir
- Qué marco de prueba usar
- Dónde hablar con Selenium Server
Ejemplo
El siguiente es el script simple, config.js, que tiene la prueba
// config.js
exports.config = {
directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
// Spec patterns are relative to the current working directory when
// protractor is called.
specs: ['TestSpecification.js'],
Explicación del código
El código del archivo de configuración anterior que tiene tres parámetros básicos, se puede explicar de la siguiente manera:
Parámetro de capacidades
Este parámetro se utiliza para especificar el nombre del navegador. Se puede ver en el siguiente bloque de código del archivo conf.js:
exports.config = {
directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
Como se vio anteriormente, el nombre del navegador que se proporciona aquí es 'chrome', que es el navegador predeterminado para Transportador. También podemos cambiar el nombre del navegador.
Parámetro de marco
Este parámetro se utiliza para especificar el nombre del marco de prueba. Se puede ver en el siguiente bloque de código del archivo config.js:
exports.config = {
directConnect: true,
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
Aquí estamos usando el marco de prueba 'jazmín'.
Parámetro de declaración de archivo de origen
Este parámetro se utiliza para especificar el nombre de la declaración del archivo fuente. Se puede ver en el siguiente bloque de código del archivo conf.js:
exports.config = {
directConnect: true,
// Spec patterns are relative to the current working
directory when protractor is called.
specs: ['TsetSpecification.js'],
Como se vio arriba, el nombre de la declaración del archivo fuente dado aquí es ‘TestSpecification.js’. Es porque, para este ejemplo, hemos creado el archivo de especificación con el nombreTestSpecification.js.
Ejecutando el código
Como tenemos conocimientos básicos sobre los archivos necesarios y su codificación para ejecutar Transportador, intentemos ejecutar el ejemplo. Podemos seguir los siguientes pasos para ejecutar este ejemplo:
Step 1 - Primero, abra el símbolo del sistema.
Step 2 - A continuación, debemos ir al directorio donde hemos guardado nuestros archivos, a saber, config.js y TestSpecification.js.
Step 3 - Ahora, ejecute el archivo config.js ejecutando el comando Protrcator config.js.
La captura de pantalla que se muestra a continuación explicará los pasos anteriores para ejecutar el ejemplo:
Se ve en la captura de pantalla que la prueba ha sido superada.
Ahora, suponga que si estamos probando sitios web no angulares y no ponemos la etiqueta ignoreSynchronization en verdadero, luego de ejecutar el código obtendremos el error "Angular no se pudo encontrar en la página".
Se puede ver en la siguiente captura de pantalla:
La generación del informe
Hasta ahora, hemos hablado sobre los archivos necesarios y su codificación para ejecutar casos de prueba. Transportador también puede generar el informe para casos de prueba. Para ello, apoya a Jasmine. JunitXMLReporter se puede utilizar para generar informes de ejecución de pruebas automáticamente.
Pero antes de eso, necesitamos instalar Jasmine Reporter con la ayuda del siguiente comando:
npm install -g jasmine-reporters
Como puede ver, la opción -g se usa al instalar Jasmine Reporters, es porque hemos instalado Protractor globalmente, con la opción -g.
Después de instalar con éxito jasmine-reporters, necesitamos agregar el siguiente código en nuestro archivo config.js usado anteriormente:
onPrepare: function(){ //configure junit xml report
var jasmineReporters = require('jasmine-reporters');
jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
consolidateAll: true,
filePrefix: 'guitest-xmloutput',
savePath: 'test/reports'
}));
Ahora, nuestro nuevo archivo config.js sería el siguiente:
// An example configuration file.
exports.config = {
directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
// Spec patterns are relative to the current working directory when
// protractor is called.
specs: ['TestSpecification.js'],
//framework: "jasmine2", //must set it if you use JUnitXmlReporter
onPrepare: function(){ //configure junit xml report
var jasmineReporters = require('jasmine-reporters');
jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
consolidateAll: true,
filePrefix: 'guitest-xmloutput',
savePath: 'reports'
}));
},
};
Después de ejecutar el archivo de configuración anterior de la misma manera, lo hemos ejecutado anteriormente, generará un archivo XML que contiene el informe en el directorio raíz en reportscarpeta. Si la prueba tuvo éxito, el informe se verá a continuación:
Pero, si la prueba falló, el informe se verá como se muestra a continuación:
Transportador - Core APIS
Este capítulo le permite comprender varias API principales que son clave para el funcionamiento del transportador.
Importancia de las API de transportador
Protractor nos proporciona una amplia gama de API que son muy importantes para realizar las siguientes acciones para obtener el estado actual del sitio web:
- Obteniendo los elementos DOM de la página web que vamos a probar.
- Interactuar con los elementos DOM.
- Asignarles acciones.
- Compartiendo información con ellos.
Para realizar las tareas anteriores, es muy importante comprender las API de transportador.
Varias API de transportador
Como sabemos, Protractor es un envoltorio de Selenium-WebDriver, que son los enlaces de WebDriver para Node.js. Transportador tiene las siguientes API:
Navegador
Es un envoltorio alrededor de una instancia de WebDriver que se usa para manejar comandos de nivel de navegador como navegación, información de toda la página, etc. Por ejemplo, el método browser.get carga una página.
Elemento
Se utiliza para buscar e interactuar con el elemento DOM en la página que estamos probando. Para ello, requiere un parámetro para localizar el elemento.
Localizadores (por)
Es una colección de estrategias de localización de elementos. Los elementos, por ejemplo, se pueden encontrar mediante el selector de CSS, por ID o por cualquier otro atributo al que estén vinculados con ng-model.
A continuación, analizaremos en detalle estas API y sus funciones.
API del navegador
Como se discutió anteriormente, es un contenedor alrededor de una instancia de WebDriver para manejar comandos de nivel de navegador. Realiza varias funciones de la siguiente manera:
Funciones y sus descripciones
Las funciones de la API de ProtractorBrowser son las siguientes:
browser.angularAppRoot
Esta función de la API del navegador establece el selector de CSS para un elemento en el que vamos a encontrar Angular. Por lo general, esta función está en 'cuerpo', pero en caso de que sea nuestra ng-app, está en una subsección de la página; también puede ser un subelemento.
browser.waitForAngularEnabled
Esta función de la API del navegador se puede establecer en verdadero o falso. Como sugiere el nombre, si esta función está configurada como falsa, Transportador no esperará a Angular$http and $tareas de tiempo de espera para completar antes de interactuar con el navegador. También podemos leer el estado actual sin cambiarlo llamando a waitForAngularEnabled () sin pasar un valor.
browser.getProcessedConfig
Con la ayuda de esta función de las API del navegador, podemos obtener el objeto de configuración procesado, incluidas las especificaciones y capacidades, que se está ejecutando actualmente.
browser.forkNewDriverInstance
Como sugiere el nombre, esta función bifurcará otra instancia de navegador que se utilizará en pruebas interactivas. Se puede ejecutar con el flujo de control habilitado y deshabilitado. A continuación se muestra un ejemplo para ambos casos:
Example 1
Corriendo browser.forkNewDriverInstance() con control de flujo habilitado -
var fork = browser.forkNewDriverInstance();
fork.get(‘page1’);
Example 2
Corriendo browser.forkNewDriverInstance() con control de flujo desactivado -
var fork = await browser.forkNewDriverInstance().ready;
await forked.get(‘page1’);
browser.restart
Como sugiere el nombre, reiniciará el navegador cerrando la instancia del navegador y creando una nueva. También puede funcionar con el flujo de control habilitado y deshabilitado. A continuación se muestra un ejemplo para ambos casos:
Example 1 - Corriendo browser.restart() con control de flujo habilitado -
browser.get(‘page1’);
browser.restart();
browser.get(‘page2’);
Example 2 - Corriendo browser.forkNewDriverInstance() con control de flujo desactivado -
await browser.get(‘page1’);
await browser.restart();
await browser.get(‘page2’);
browser.restartSync
Es similar a la función browser.restart (). La única diferencia es que devuelve la nueva instancia del navegador directamente en lugar de devolver una promesa que se resuelve en la nueva instancia del navegador. Solo se puede ejecutar cuando el flujo de control está habilitado.
Example - Corriendo browser.restartSync() con control de flujo habilitado -
browser.get(‘page1’);
browser.restartSync();
browser.get(‘page2’);
browser.useAllAngular2AppRoots
Como sugiere el nombre, solo es compatible con Angular2. Buscará en todas las aplicaciones angulares disponibles en la página mientras encuentra elementos o espera la estabilidad.
browser.waitForAngular
Esta función de la API del navegador indica al WebDriver que espere hasta que Angular haya terminado de renderizarse y no tenga pendientes $http or $llamadas de tiempo de espera antes de continuar.
browser.findElement
Como sugiere el nombre, esta función de la API del navegador espera a que Angular termine de renderizarse antes de buscar el elemento.
browser.isElementPresent
Como sugiere el nombre, esta función de la API del navegador probará si el elemento está presente en la página o no.
browser.addMockModule
Agregará un módulo para cargar antes de Angular cada vez que se llame al método Protractor.get.
Example
browser.addMockModule('modName', function() {
angular.module('modName', []).value('foo', 'bar');
});
browser.clearMockModules
a diferencia de browser.addMockModule, borrará la lista de módulos simulados registrados.
browser.removeMockModule
Como su nombre indica, eliminará un módulo de simulación de registro. Ejemplo: browser.removeMockModule ('modName');
browser.getRegisteredMockModules
Frente a browser.clearMockModule, obtendrá la lista de módulos simulados registrados.
browser.get
Podemos usar browser.get () para navegar el navegador a una dirección web en particular y cargar los módulos simulados para esa página antes de la carga angular.
Example
browser.get(url);
browser.get('http://localhost:3000');
// This will navigate to the localhost:3000 and will load mock module if needed
browser.refresh
Como sugiere el nombre, esto recargará la página actual y cargará módulos simulados antes de Angular.
browser.navigate
Como sugiere el nombre, se utiliza para mezclar métodos de navegación en el objeto de navegación para que se invoquen como antes. Ejemplo: driver.navigate (). Refresh ().
browser.setLocation
Se utiliza para navegar a otra página utilizando la navegación dentro de la página.
Example
browser.get('url/ABC');
browser.setLocation('DEF');
expect(browser.getCurrentUrl())
.toBe('url/DEF');
Navegará de la página ABC a la DEF.
browser.debugger
Como sugiere el nombre, esto debe usarse con la depuración del transportador. Básicamente, esta función agrega una tarea al flujo de control para pausar la prueba e inyectar funciones de ayuda en el navegador para que la depuración se pueda realizar en la consola del navegador.
browser.pause
Se utiliza para depurar pruebas de WebDriver. Nosotros podemos usarbrowser.pause() en nuestra prueba para ingresar al depurador de transportador desde ese punto en el flujo de control.
Example
element(by.id('foo')).click();
browser.pause();
// Execution will stop before the next click action.
element(by.id('bar')).click();
browser.controlFlowEnabled
Se utiliza para determinar si el flujo de control está habilitado o no.
Transportador - Núcleo APIS (CONT.…)
En este capítulo, aprendamos algunas API principales de Transportador.
API de elementos
El elemento es una de las funciones globales expuestas por transportador. Esta función toma un localizador y devuelve lo siguiente:
- ElementFinder, que encuentra un solo elemento basado en el localizador.
- ElementArrayFinder, que encuentra una matriz de elementos basada en el localizador.
Ambos métodos de encadenamiento de soporte anteriores como se describe a continuación.
Encadenamiento de funciones de ElementArrayFinder y sus descripciones
Las siguientes son las funciones de ElementArrayFinder:
element.all(locator).clone
Como sugiere el nombre, esta función creará una copia superficial de la matriz de elementos, es decir, ElementArrayFinder.
element.all(locator).all(locator)
Básicamente, esta función devuelve un nuevo ElementArrayFinder que podría estar vacío o contener los elementos secundarios. Se puede utilizar para seleccionar varios elementos como una matriz de la siguiente manera
Example
element.all(locator).all(locator)
elementArr.all(by.css(‘.childselector’));
// it will return another ElementFindArray as child element based on child locator.
element.all(locator).filter(filterFn)
Como sugiere el nombre, después de aplicar la función de filtro a cada elemento dentro de ElementArrayFinder, devuelve un nuevo ElementArrayFinder con todos los elementos que pasan la función de filtro. Básicamente tiene dos argumentos, el primero es ElementFinder y el segundo es index. También se puede utilizar en objetos de página.
Example
View
<ul class = "items">
<li class = "one">First</li>
<li class = "two">Second</li>
<li class = "three">Third</li>
</ul>
Code
element.all(by.css('.items li')).filter(function(elem, index) {
return elem.getText().then(function(text) {
return text === 'Third';
});
}).first().click();
element.all(locator).get(index)
Con la ayuda de esto, podemos obtener un elemento dentro de ElementArrayFinder por índice. Tenga en cuenta que el índice comienza en 0 y los índices negativos se envuelven.
Example
View
<ul class = "items">
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
Code
let list = element.all(by.css('.items li'));
expect(list.get(0).getText()).toBe('First');
expect(list.get(1).getText()).toBe('Second');
element.all(locator).first()
Como sugiere el nombre, esto obtendrá el primer elemento para ElementArrayFinder. No recuperará el elemento subyacente.
Example
View
<ul class = "items">
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
Code
let first = element.all(by.css('.items li')).first();
expect(first.getText()).toBe('First');
element.all(locator).last()
Como sugiere el nombre, esto obtendrá el último elemento de ElementArrayFinder. No recuperará el elemento subyacente.
Example
View
<ul class = "items">
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
Code
let first = element.all(by.css('.items li')).last();
expect(last.getText()).toBe('Third');
element.all(locator).all(selector)
Se usa para encontrar una matriz de elementos dentro de un padre cuando las llamadas a $$ pueden estar encadenadas.
Example
View
<div class = "parent">
<ul>
<li class = "one">First</li>
<li class = "two">Second</li>
<li class = "three">Third</li>
</ul>
</div>
Code
let items = element(by.css('.parent')).$$('li');
element.all(locator).count()
Como sugiere el nombre, esto contará el número de elementos representados por ElementArrayFinder. No recuperará el elemento subyacente.
Example
View
<ul class = "items">
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
Code
let list = element.all(by.css('.items li'));
expect(list.count()).toBe(3);
element.all(locator).isPresent()
Hará coincidir los elementos con el buscador. Puede devolver verdadero o falso. Verdadero, si hay elementos presentes que coincidan con el buscador y Falso en caso contrario.
Example
expect($('.item').isPresent()).toBeTruthy();
element.all(locator).locator
Como sugiere el nombre, devolverá el localizador más relevante.
Example
$('#ID1').locator();
// returns by.css('#ID1')
$('#ID1').$('#ID2').locator();
// returns by.css('#ID2')
$$('#ID1').filter(filterFn).get(0).click().locator();
// returns by.css('#ID1')
element.all(locator).then(thenFunction)
Recuperará los elementos representados por ElementArrayFinder.
Example
View
<ul class = "items">
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
Code
element.all(by.css('.items li')).then(function(arr) {
expect(arr.length).toEqual(3);
});
element.all(locator).each(eachFunction)
Como sugiere el nombre, llamará a la función de entrada en cada ElementFinder representado por ElementArrayFinder.
Example
View
<ul class = "items">
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
Code
element.all(by.css('.items li')).each(function(element, index) {
// It will print First 0, Second 1 and Third 2.
element.getText().then(function (text) {
console.log(index, text);
});
});
element.all(locator).map(mapFunction)
Como sugiere el nombre, aplicará una función de mapa en cada elemento dentro de ElementArrayFinder. Tiene dos argumentos. Primero sería ElementFinder y segundo sería el índice.
Example
View
<ul class = "items">
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
Code
let items = element.all(by.css('.items li')).map(function(elm, index) {
return {
index: index,
text: elm.getText(),
class: elm.getAttribute('class')
};
});
expect(items).toEqual([
{index: 0, text: 'First', class: 'one'},
{index: 1, text: 'Second', class: 'two'},
{index: 2, text: 'Third', class: 'three'}
]);
element.all(locator).reduce(reduceFn)
Como sugiere el nombre, aplicará una función de reducción contra un acumulador y cada elemento encontrado usando el localizador. Esta función reducirá cada elemento a un solo valor.
Example
View
<ul class = "items">
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
Code
let value = element.all(by.css('.items li')).reduce(function(acc, elem) {
return elem.getText().then(function(text) {
return acc + text + ' ';
});
}, '');
expect(value).toEqual('First Second Third ');
element.all(locator).evaluate
Como sugiere el nombre, evaluará la entrada si está dentro del alcance de los elementos subyacentes actuales o no.
Example
View
<span class = "foo">{{letiableInScope}}</span>
Code
let value =
element.all(by.css('.foo')).evaluate('letiableInScope');
element.all(locator).allowAnimations
Como sugiere el nombre, determinará si la animación está permitida en los elementos subyacentes actuales o no.
Example
element(by.css('body')).allowAnimations(false);
Encadenamiento de funciones de ElementFinder y sus descripciones
Encadenamiento de funciones de ElementFinder y sus descripciones -
element(locator).clone
Como sugiere el nombre, esta función creará una copia superficial del ElementFinder.
element(locator).getWebElement()
Devolverá el WebElement representado por este ElementFinder y se lanzará un error WebDriver si el elemento no existe.
Example
View
<div class="parent">
some text
</div>
Code
// All the four following expressions are equivalent.
$('.parent').getWebElement();
element(by.css('.parent')).getWebElement();
browser.driver.findElement(by.css('.parent'));
browser.findElement(by.css('.parent'));
element(locator).all(locator)
Encontrará una matriz de elementos dentro de un padre.
Example
View
<div class = "parent">
<ul>
<li class = "one">First</li>
<li class = "two">Second</li>
<li class = "three">Third</li>
</ul>
</div>
Code
let items = element(by.css('.parent')).all(by.tagName('li'));
element(locator).element(locator)
Encontrará elementos dentro de un padre.
Example
View
<div class = "parent">
<div class = "child">
Child text
<div>{{person.phone}}</div>
</div>
</div>
Code
// Calls Chain 2 element.
let child = element(by.css('.parent')).
element(by.css('.child'));
expect(child.getText()).toBe('Child text\n981-000-568');
// Calls Chain 3 element.
let triple = element(by.css('.parent')).
element(by.css('.child')).
element(by.binding('person.phone'));
expect(triple.getText()).toBe('981-000-568');
element(locator).all(selector)
Encontrará una matriz de elementos dentro de un padre cuando las llamadas a $$ puedan estar encadenadas.
Example
View
<div class = "parent">
<ul>
<li class = "one">First</li>
<li class = "two">Second</li>
<li class = "three">Third</li>
</ul>
</div>
Code
let items = element(by.css('.parent')).$$('li'));
element(locator).$(locator)
Encontrará elementos dentro de un padre cuando las llamadas a $ puedan estar encadenadas.
Example
View
<div class = "parent">
<div class = "child">
Child text
<div>{{person.phone}}</div>
</div>
</div>
Code
// Calls Chain 2 element.
let child = element(by.css('.parent')).
$('.child')); expect(child.getText()).toBe('Child text\n981-000-568'); // Calls Chain 3 element. let triple = element(by.css('.parent')). $('.child')).
element(by.binding('person.phone'));
expect(triple.getText()).toBe('981-000-568');
element(locator).isPresent()
Determinará si el elemento se presenta en la página o no.
Example
View
<span>{{person.name}}</span>
Code
expect(element(by.binding('person.name')).isPresent()).toBe(true);
// will check for the existence of element
expect(element(by.binding('notPresent')).isPresent()).toBe(false);
// will check for the non-existence of element
element(locator).isElementPresent()
Es lo mismo que element (locator) .isPresent (). La única diferencia es que comprobará si el elemento identificado por sublocator está presente en lugar del buscador de elementos actual.
element.all(locator).evaluate
Como sugiere el nombre, evaluará la entrada si está en el alcance de los elementos subyacentes actuales o no.
Example
View
<span id = "foo">{{letiableInScope}}</span>
Code
let value = element(by.id('.foo')).evaluate('letiableInScope');
element(locator).allowAnimations
Como sugiere el nombre, determinará si la animación está permitida en los elementos subyacentes actuales o no.
Example
element(by.css('body')).allowAnimations(false);
element(locator).equals
Como sugiere el nombre, comparará un elemento para determinar la igualdad.
Localizadores (por) API
Básicamente es una colección de estrategias de localizador de elementos que proporciona formas de encontrar elementos en aplicaciones angulares mediante enlace, modelo, etc.
Functions and their descriptions
Las funciones de la API de ProtractorLocators son las siguientes:
by.addLocator(locatorName,fuctionOrScript)
Agregará un localizador a esta instancia de ProtrcatorBy que además se puede usar con element (by.locatorName (args)).
Example
View
<button ng-click = "doAddition()">Go!</button>
Code
// Adding the custom locator.
by.addLocator('buttonTextSimple',
function(buttonText, opt_parentElement, opt_rootSelector) {
var using = opt_parentElement || document,
buttons = using.querySelectorAll('button');
return Array.prototype.filter.call(buttons, function(button) {
return button.textContent === buttonText;
});
});
element(by.buttonTextSimple('Go!')).click();// Using the custom locator.
by.binding
Como sugiere el nombre, encontrará un elemento por enlace de texto. Se realizará una coincidencia parcial para que se devuelva cualquier elemento vinculado a las variables que contienen la cadena de entrada.
Example
View
<span>{{person.name}}</span>
<span ng-bind = "person.email"></span>
Code
var span1 = element(by.binding('person.name'));
expect(span1.getText()).toBe('Foo');
var span2 = element(by.binding('person.email'));
expect(span2.getText()).toBe('[email protected]');
by.exactbinding
Como sugiere el nombre, encontrará un elemento por enlace exacto.
Example
View
<spangt;{{ person.name }}</spangt;
<span ng-bind = "person-email"gt;</spangt;
<spangt;{{person_phone|uppercase}}</span>
Code
expect(element(by.exactBinding('person.name')).isPresent()).toBe(true);
expect(element(by.exactBinding('person-email')).isPresent()).toBe(true);
expect(element(by.exactBinding('person')).isPresent()).toBe(false);
expect(element(by.exactBinding('person_phone')).isPresent()).toBe(true);
expect(element(by.exactBinding('person_phone|uppercase')).isPresent()).toBe(true);
expect(element(by.exactBinding('phone')).isPresent()).toBe(false);
by.model(modelName)
Como sugiere el nombre, encontrará un elemento mediante la expresión ng-model.
Example
View
<input type = "text" ng-model = "person.name">
Code
var input = element(by.model('person.name'));
input.sendKeys('123');
expect(input.getAttribute('value')).toBe('Foo123');
by.buttonText
Como sugiere el nombre, encontrará un botón por texto.
Example
View
<button>Save</button>
Code
element(by.buttonText('Save'));
by.partialButtonText
Como sugiere el nombre, encontrará un botón por texto parcial.
Example
View
<button>Save my file</button>
Code
element(by.partialButtonText('Save'));
by.repeater
Como sugiere el nombre, encontrará un elemento dentro de una repetición ng.
Example
View
<div ng-repeat = "cat in pets">
<span>{{cat.name}}</span>
<span>{{cat.age}}</span>
<</div>
<div class = "book-img" ng-repeat-start="book in library">
<span>{{$index}}</span>
</div>
<div class = "book-info" ng-repeat-end>
<h4>{{book.name}}</h4>
<p>{{book.blurb}}</p>
</div>
Code
var secondCat = element(by.repeater('cat in
pets').row(1)); // It will return the DIV for the second cat.
var firstCatName = element(by.repeater('cat in pets').
row(0).column('cat.name')); // It will return the SPAN for the first cat's name.
by.exactRepeater
Como sugiere el nombre, encontrará un elemento por repetidor exacto.
Example
View
<li ng-repeat = "person in peopleWithRedHair"></li>
<li ng-repeat = "car in cars | orderBy:year"></li>
Code
expect(element(by.exactRepeater('person in
peopleWithRedHair')).isPresent())
.toBe(true);
expect(element(by.exactRepeater('person in
people')).isPresent()).toBe(false);
expect(element(by.exactRepeater('car in cars')).isPresent()).toBe(true);
by.cssContainingText
Como sugiere el nombre, encontrará los elementos, que contienen la cadena exacta, por CSS
Example
View
<ul>
<li class = "pet">Dog</li>
<li class = "pet">Cat</li>
</ul>
Code
var dog = element(by.cssContainingText('.pet', 'Dog'));
// It will return the li for the dog, but not for the cat.
by.options(optionsDescriptor)
Como sugiere el nombre, encontrará un elemento mediante la expresión ng-options.
Example
View
<select ng-model = "color" ng-options = "c for c in colors">
<option value = "0" selected = "selected">red</option>
<option value = "1">green</option>
</select>
Code
var allOptions = element.all(by.options('c for c in colors'));
expect(allOptions.count()).toEqual(2);
var firstOption = allOptions.first();
expect(firstOption.getText()).toEqual('red');
by.deepCSS(selector)
Como sugiere el nombre, encontrará un elemento mediante el selector de CSS dentro de la sombra DOM.
Example
View
<div>
<span id = "outerspan">
<"shadow tree">
<span id = "span1"></span>
<"shadow tree">
<span id = "span2"></span>
</>
</>
</div>
Code
var spans = element.all(by.deepCss('span'));
expect(spans.count()).toEqual(3);
Transportador - Objetos
Este capítulo trata en detalle sobre los objetos en Transportador.
¿Qué son los objetos de página?
El objeto de página es un patrón de diseño que se ha vuelto popular para escribir pruebas e2e con el fin de mejorar el mantenimiento de la prueba y reducir la duplicación de código. Puede definirse como una clase orientada a objetos que sirve como interfaz para una página de su AUT (aplicación bajo prueba). Pero, antes de profundizar en los objetos de la página, debemos comprender los desafíos de las pruebas de IU automatizadas y las formas de manejarlos.
Desafíos con las pruebas de IU automatizadas
Los siguientes son algunos desafíos comunes con las pruebas de IU automatizadas:
Cambios en la interfaz de usuario
Los problemas más comunes al trabajar con pruebas de IU son los cambios que ocurren en la IU. Por ejemplo, sucede la mayor parte del tiempo que los botones o cuadros de texto, etc., generalmente tienen cambios y crean problemas para las pruebas de IU.
Falta de compatibilidad con DSL (lenguaje específico de dominio)
Otro problema con las pruebas de IU es la falta de compatibilidad con DSL. Con este problema, resulta muy difícil comprender qué se está probando.
Mucha repetición / duplicación de código
El siguiente problema común en las pruebas de IU es que hay mucha repetición o duplicación de código. Se puede entender con la ayuda de las siguientes líneas de código:
element(by.model(‘event.name’)).sendKeys(‘An Event’);
element(by.model(‘event.name’)).sendKeys(‘Module 3’);
element(by.model(‘event.name’));
Mantenimiento riguroso
Debido a los desafíos anteriores, el mantenimiento se convierte en un dolor de cabeza. Es porque tenemos que encontrar todas las instancias, reemplazar con el nuevo nombre, selector y otro código. También necesitamos dedicar mucho tiempo a mantener las pruebas en línea con la refactorización.
Pruebas rotas
Otro desafío en las pruebas de IU es la ocurrencia de muchos fallos en las pruebas.
Formas de afrontar los desafíos
Hemos visto algunos desafíos comunes de las pruebas de IU. Algunas de las formas de manejar tales desafíos son las siguientes:
Actualizar referencias manualmente
La primera opción para manejar los desafíos anteriores es actualizar las referencias manualmente. El problema con esta opción es que debemos hacer el cambio manual en el código así como nuestras pruebas. Esto se puede hacer cuando tiene uno o dos archivos de prueba, pero ¿qué sucede si tiene cientos de archivos de prueba en un proyecto?
Usar objetos de página
Otra opción para manejar los desafíos anteriores es usar objetos de página. Un objeto de página es básicamente un JavaScript simple que encapsula las propiedades de una plantilla angular. Por ejemplo, el siguiente archivo de especificación se escribe sin y con objetos de página para comprender la diferencia:
Without Page Objects
describe('angularjs homepage', function() {
it('should greet the named user', function() {
browser.get('http://www.angularjs.org');
element(by.model('yourName')).sendKeys('Julie');
var greeting = element(by.binding('yourName'));
expect(greeting.getText()).toEqual('Hello Julie!');
});
});
With Page Objects
Para escribir el código con objetos de página, lo primero que debemos hacer es crear un objeto de página. Por lo tanto, un objeto de página para el ejemplo anterior podría verse así:
var AngularHomepage = function() {
var nameInput = element(by.model('yourName'));
var greeting = element(by.binding('yourName'));
this.get = function() {
browser.get('http://www.angularjs.org');
};
this.setName = function(name) {
nameInput.sendKeys(name);
};
this.getGreetingText = function() {
return greeting.getText();
};
};
module.exports = new AngularHomepage();
Uso de objetos de página para organizar pruebas
Hemos visto el uso de objetos de página en el ejemplo anterior para manejar los desafíos de las pruebas de IU. A continuación, vamos a discutir cómo podemos usarlos para organizar las pruebas. Para esto, necesitamos modificar el script de prueba sin modificar la funcionalidad del script de prueba.
Ejemplo
Para comprender este concepto, tomamos el archivo de configuración anterior con objetos de página. Necesitamos modificar el script de prueba de la siguiente manera:
var angularHomepage = require('./AngularHomepage');
describe('angularjs homepage', function() {
it('should greet the named user', function() {
angularHomepage.get();
angularHomepage.setName('Julie');
expect(angularHomepage.getGreetingText()).toEqual
('Hello Julie!');
});
});
Aquí, tenga en cuenta que la ruta al objeto de la página será relativa a su especificación.
En la misma nota, también podemos separar nuestro conjunto de pruebas en varios conjuntos de pruebas. El archivo de configuración se puede cambiar de la siguiente manera
exports.config = {
// The address of a running selenium server.
seleniumAddress: 'http://localhost:4444/wd/hub',
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
// Spec patterns are relative to the location of the spec file. They may
// include glob patterns.
suites: {
homepage: 'tests/e2e/homepage/**/*Spec.js',
search: ['tests/e2e/contact_search/**/*Spec.js',
'tests/e2e/venue_search/**/*Spec.js']
},
// Options to be passed to Jasmine-node.
jasmineNodeOpts: {
showColors: true, // Use colors in the command line report.
}
};
Ahora, podemos cambiar fácilmente entre ejecutar una u otra suite de pruebas. El siguiente comando ejecutará solo la sección de la página de inicio de la prueba:
protractor protractor.conf.js --suite homepage
De manera similar, podemos ejecutar conjuntos de pruebas específicos con el comando de la siguiente manera:
protractor protractor.conf.js --suite homepage,search
Transportador - Depuración
Ahora que hemos visto todos los conceptos de transportador en los capítulos anteriores, comprendamos los conceptos de depuración en detalle en este capítulo.
Introducción
Las pruebas de extremo a extremo (e2e) son muy difíciles de depurar porque dependen de todo el ecosistema de esa aplicación. Hemos visto que dependen de varias acciones o en particular podemos decir que de acciones previas como el inicio de sesión y en ocasiones dependen del permiso. Otra dificultad para depurar las pruebas de e2e es su dependencia de WebDriver porque actúa de manera diferente con diferentes sistemas operativos y navegadores. Por último, la depuración de las pruebas de e2e también genera largos mensajes de error y dificulta la separación de los problemas relacionados con el navegador y los errores del proceso de prueba.
Tipos de fallas
Puede haber varias razones para el fracaso de las suites de prueba y los siguientes son algunos tipos de fallas bien conocidos:
Fallo de WebDriver
Cuando no se puede completar un comando, WebDriver emite un error. Por ejemplo, un navegador no puede obtener la dirección definida o un elemento no se encuentra como se esperaba.
Error inesperado de WebDriver
Se produce una falla inesperada del navegador y del sistema operativo cuando no se actualiza el administrador de controladores web.
Fallo del transportador para Angular
La falla de Transportador para Angular ocurre cuando Transportador no encontró Angular en la biblioteca como se esperaba.
Transportador Angular2 falla
En este tipo de falla, Protractor fallará cuando el parámetro useAllAngular2AppRoots no se encuentre en la configuración. Sucede porque, sin esto, el proceso de prueba observará un único elemento raíz mientras espera más de un elemento en el proceso.
Fallo del transportador por tiempo de espera
Este tipo de falla ocurre cuando la especificación de prueba golpea un bucle o un grupo largo y no devuelve los datos a tiempo.
Expectativa fracaso
Una de las fallas de prueba más comunes que muestra cómo se ve una falla de expectativa normal.
¿Por qué la depuración es importante en Transportador?
Supongamos que, si ha escrito casos de prueba y fallaron, es muy importante saber cómo depurar esos casos de prueba porque sería muy difícil encontrar el lugar exacto donde ocurrió el error. Mientras trabaja con Transportador, obtendrá algunos errores largos en la fuente de color rojo en la línea de comando.
Pausar y depurar la prueba
Las formas de depurar en Transportador se explican aquí & miuns;
Método de pausa
Usar el método de pausa para depurar los casos de prueba en Transportador es una de las formas más fáciles. Podemos escribir el siguiente comando en el lugar donde queremos pausar nuestro código de prueba & miuns;
browser.pause();
Cuando los códigos en ejecución golpean el comando anterior, pausará el programa en ejecución en ese punto. Después de eso, podemos dar los siguientes comandos según nuestra preferencia:
Tipo C para avanzar
Siempre que un comando se haya agotado, debemos teclear C para avanzar. Si no escribe C, la prueba no ejecutará el código completo y fallará debido al error de tiempo de espera de Jasmine.
Escriba repl para ingresar al modo interactivo
El beneficio del modo interactivo es que podemos enviar los comandos de WebDriver a nuestro navegador. Si queremos entrar al modo interactivo, entonces tecleamosrepl.
Escriba Ctrl-C para salir y continuar las pruebas
Para salir de la prueba del estado de pausa y continuar la prueba desde donde se detuvo, debemos escribir Ctrl-C.
Ejemplo
En este ejemplo, tenemos el archivo de especificación siguiente llamado example_debug.js, el transportador intenta identificar un elemento con el localizador by.binding('mmmm') pero la URL (https://angularjs.org/ la página no tiene ningún elemento con el localizador especificado.
describe('Suite for protractor debugger',function(){
it('Failing spec',function(){
browser.get("http://angularjs.org");
element(by.model('yourName')).sendKeys('Vijay');
//Element doesn't exist
var welcomeText =
element(by.binding('mmmm')).getText();
expect('Hello '+welcomeText+'!').toEqual('Hello Ram!')
});
});
Ahora, para ejecutar la prueba anterior, debemos agregar el código browser.pause (), donde desea pausar la prueba, en el archivo de especificación anterior. Se verá de la siguiente manera:
describe('Suite for protractor debugger',function(){
it('Failing spec',function(){
browser.get("http://angularjs.org");
browser.pause();
element(by.model('yourName')).sendKeys('Vijay');
//Element doesn't exist
var welcomeText =
element(by.binding('mmmm')).getText();
expect('Hello '+welcomeText+'!').toEqual('Hello Ram!')
});
});
Pero antes de ejecutar, también necesitamos hacer algunos cambios en el archivo de configuración. Estamos haciendo los siguientes cambios en el archivo de configuración usado anteriormente, llamadoexample_configuration.js en el capítulo anterior -
// An example configuration file.
exports.config = {
directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
// Spec patterns are relative to the current working directory when
// protractor is called.
specs: ['example_debug.js'],
allScriptsTimeout: 999999,
jasmineNodeOpts: {
defaultTimeoutInterval: 999999
},
onPrepare: function () {
browser.manage().window().maximize();
browser.manage().timeouts().implicitlyWait(5000);
}
};
Ahora, ejecute el siguiente comando:
protractor example_configuration.js
El depurador se iniciará después del comando anterior.
Método de depuración
Usar el método de pausa para depurar los casos de prueba en Transportador es una forma un poco avanzada. Podemos escribir el siguiente comando en el lugar donde queremos romper nuestro código de prueba:
browser.debugger();
Utiliza el depurador de nodos para depurar el código de prueba. Para ejecutar el comando anterior, debemos escribir el siguiente comando en un símbolo del sistema separado que se ha abierto desde la ubicación del proyecto de prueba:
protractor debug protractor.conf.js
En este método, también necesitamos escribir C en la terminal para continuar con el código de prueba. Pero al contrario del método de pausa, en este método se debe escribir solo una vez.
Ejemplo
En este ejemplo, estamos usando el mismo archivo de especificación llamado bexample_debug.js, usado arriba. La única diferencia es que en lugar debrowser.pause(), necesitamos usar browser.debugger()donde queremos romper el código de prueba. Se verá de la siguiente manera:
describe('Suite for protractor debugger',function(){
it('Failing spec',function(){
browser.get("http://angularjs.org");
browser.debugger();
element(by.model('yourName')).sendKeys('Vijay');
//Element doesn't exist
var welcomeText = element(by.binding('mmmm')).getText();
expect('Hello '+welcomeText+'!').toEqual('Hello Ram!')
});
});
Estamos usando el mismo archivo de configuración, example_configuration.js, utilizado en el ejemplo anterior.
Ahora, ejecute la prueba del transportador con la siguiente opción de línea de comando de depuración
protractor debug example_configuration.js
El depurador se iniciará después del comando anterior.
Transportador - Guía de estilo para transportador
En este capítulo, aprendamos en detalle sobre la guía de estilo para transportador.
Introducción
La guía de estilo fue creada por dos ingenieros de software llamados, Carmen Popoviciu, ingeniero de front-end en ING y Andres Dominguez, ingeniero de software en Google. Por lo tanto, esta guía de estilo también se llama Carmen Popoviciu y guía de estilo de Google para transportador.
Esta guía de estilo se puede dividir en los siguientes cinco puntos clave:
- Reglas genéricas
- Estructura del proyecto
- Estrategias de localización
- Objetos de página
- Suites de prueba
Reglas genéricas
Las siguientes son algunas reglas genéricas que deben tenerse en cuenta al usar el transportador para las pruebas:
No pruebe de un extremo a otro lo que ya ha sido probado por unidad
Esta es la primera regla genérica dada por Carmen y Andrés. Sugirieron que no debemos realizar la prueba e2e en el código que ya ha sido probado por unidad. La principal razón detrás de esto es que las pruebas unitarias son mucho más rápidas que las pruebas e2e. Otra razón es que debemos evitar las pruebas duplicadas (no realice pruebas tanto unitarias como e2e) para ahorrar tiempo.
Use solo un archivo de configuración
Otro punto importante recomendado es que debemos tener que usar solo un archivo de configuración. No cree un archivo de configuración para cada entorno que esté probando. Puedes usargrunt-protractor-coverage para configurar diferentes entornos.
Evite usar la lógica en su prueba
Debemos evitar el uso de sentencias IF o bucles FOR en nuestros casos de prueba porque si lo hacemos, la prueba puede pasar sin probar nada o puede funcionar muy lento.
Haga que la prueba sea independiente a nivel de archivo
El transportador puede ejecutar la prueba en paralelo cuando se habilita el uso compartido. Luego, estos archivos se ejecutan en diferentes navegadores a medida que están disponibles. Carmen y Andrés recomendaron hacer la prueba independiente al menos a nivel de archivo porque el orden en el que se ejecutarán mediante transportador es incierto y, además, es bastante fácil ejecutar una prueba de forma aislada.
Estructura del proyecto
Otro punto clave importante con respecto a la guía de estilo de Transportador es la estructura de su proyecto. La siguiente es la recomendación sobre la estructura del proyecto:
Prueba e2e a tientas en una estructura sensible
Carmen y Andrés recomendaron que debemos agrupar nuestras pruebas e2e en una estructura que tenga sentido para la estructura de su proyecto. La razón detrás de esta recomendación es que la búsqueda de archivos sería fácil y la estructura de carpetas sería más legible. Este paso también separará las pruebas e2e de las pruebas unitarias. Recomendaron que se evite el siguiente tipo de estructura:
|-- project-folder
|-- app
|-- css
|-- img
|-- partials
home.html
profile.html
contacts.html
|-- js
|-- controllers
|-- directives
|-- services
app.js
...
index.html
|-- test
|-- unit
|-- e2e
home-page.js
home-spec.js
profile-page.js
profile-spec.js
contacts-page.js
contacts-spec.js
Por otro lado, recomendaron el siguiente tipo de estructura:
|-- project-folder
|-- app
|-- css
|-- img
|-- partials
home.html
profile.html
contacts.html
|-- js
|-- controllers
|-- directives
|-- services
app.js
...
index.html
|-- test
|-- unit
|-- e2e
|-- page-objects
home-page.js
profile-page.js
contacts-page.js
home-spec.js
profile-spec.js
contacts-spec.js
Estrategias de localización
Las siguientes son algunas estrategias de localización que deben tenerse en cuenta al usar el transportador para realizar pruebas:
Nunca use XPATH
Esta es la primera estrategia de localización que se recomienda en la guía de estilo del transportador. La razón detrás de esto es que XPath requiere mucho mantenimiento porque el marcado está sujeto a cambios muy fácilmente. Además, las expresiones XPath son las más lentas y muy difíciles de depurar.
Prefiera siempre localizadores específicos de transportadores como by.model y by.binding
Los localizadores específicos de transportadores como by.model y by.binding son cortos, específicos y fáciles de leer. Con la ayuda de ellos también es muy fácil escribir nuestro localizador.
Ejemplo
View
<ul class = "red">
<li>{{color.name}}</li>
<li>{{color.shade}}</li>
<li>{{color.code}}</li>
</ul>
<div class = "details">
<div class = "personal">
<input ng-model = "person.name">
</div>
</div>
Para el código anterior, se recomienda evitar lo siguiente:
var nameElement = element.all(by.css('.red li')).get(0);
var personName = element(by.css('.details .personal input'));
Por otro lado, se recomienda utilizar lo siguiente:
var nameElement = element.all(by.css('.red li')).get(0);
var personName = element(by.css('.details .personal input'));
var nameElement = element(by.binding('color.name'));
var personName = element(by.model('person.name'));
Cuando no hay localizadores de transportador disponibles, se recomienda preferir by.id y by.css.
Evite siempre los localizadores de texto para cambiar el texto con frecuencia
Debemos evitar los localizadores basados en texto como by.linkText, by.buttonText y by.cssContaningText porque el texto de los botones, enlaces y etiquetas cambia con frecuencia con el tiempo.
Objetos de página
Como se discutió anteriormente, los objetos de página encapsulan información sobre los elementos en nuestra página de aplicación y, debido a esto, nos ayudan a escribir casos de prueba más limpios. Una ventaja muy útil de los objetos de página es que se pueden reutilizar en múltiples pruebas y, en caso de que se haya cambiado la plantilla de nuestra aplicación, solo necesitamos actualizar el objeto de página. Las siguientes son algunas recomendaciones para los objetos de página que deben tenerse en cuenta al usar el transportador para las pruebas:
Para interactuar con la página bajo prueba, use objetos de página
Se recomienda utilizar objetos de página para interactuar con la página bajo prueba porque pueden encapsular información sobre el elemento en la página bajo prueba y también se pueden reutilizar.
Declare siempre un objeto de una página por archivo
Debemos definir cada objeto de página en su propio archivo porque mantiene el código limpio y la búsqueda de cosas se vuelve fácil.
Al final de la página, el archivo de objeto siempre usa un solo módulo.
Se recomienda que cada objeto de página declare una sola clase para que solo necesitemos exportar una clase. Por ejemplo, se debe evitar el siguiente uso del archivo objeto:
var UserProfilePage = function() {};
var UserSettingsPage = function() {};
module.exports = UserPropertiesPage;
module.exports = UserSettingsPage;
Pero, por otro lado, se recomienda usar lo siguiente:
/** @constructor */
var UserPropertiesPage = function() {};
module.exports = UserPropertiesPage;
Declare todos los módulos requeridos en la parte superior
Deberíamos declarar todos los módulos requeridos en la parte superior del objeto de la página porque hace que las dependencias de los módulos sean claras y fáciles de encontrar.
Cree una instancia de todos los objetos de la página al comienzo del conjunto de pruebas
Se recomienda crear una instancia de todos los objetos de página al comienzo de la suite de prueba porque esto separará las dependencias del código de prueba y hará que las dependencias estén disponibles para todas las especificaciones de la suite.
No use esperar () en objetos de página
No deberíamos usar esperar () en los objetos de la página, es decir, no deberíamos hacer ninguna afirmación en los objetos de nuestra página porque todas las afirmaciones deben hacerse en casos de prueba.
Otra razón es que el lector de la prueba debería poder comprender el comportamiento de la aplicación leyendo solo los casos de prueba.