Vous êtes sur la page 1sur 17

SELENIUM TESTING CON TEST SUITE Y UNITTEST

Realizar un script de automatización utilizando UnitTest y Selenium

Aplicar varios métodos de pruebas con UnitTest


En este tutorial de Selenium Python, cubriremos algunos de los temas clave sobre como
automatizar las aplicaciones Web usando Selenium Webdriver APIs en Python.

Antes de comenzar con la automatización de pruebas, primero debemos preparar un


conjunto de casos de prueba para las características que están activas en la aplicación Web.
Estos pueden ser casos para criterios de aceptación o parte de pruebas funcionales.

A continuación, para la automatización, necesitaremos un marco de automatización o Test


Framework que podría facilitar las capacidades de gestión de pruebas, como la creación de
pruebas basadas en datos, la creación de condiciones previas y posteriores a las pruebas, la
comprobación de los Test esperados y reales. Y lo que es más importante, debería
proporcionar capacidad de generación de informes o reportes.

Como no todas estas funciones están disponibles en Selenium WebDriver utilizaremos


el unit testing framework de Python y utilizaremos sus funciones junto con Selenium
Webdriver.

Junto con este post, le recomendamos que lea también los siguientes tutoriales. Te ayudará a
configurar Selenium con Python y configurar navegadores como Firefox, Chrome e IE.
Construya una suite de pruebas de
python con Selenium desde cero con
Unittest.
1. Entendiendo el Marco de Prueba de Python
Unittest y sus características.
La librería Python Unittest hereda su raíz de un módulo de terceros conocido como PyUnit.

El módulo Python Unittest divide su funcionalidad en cinco componentes claves. Todos los
cinco elementos trabajan en tándem para soportar las pruebas de automatización.
Discutamos cada uno de ellos en detalle.

1.1. Cinco Componentes del Marco de Prueba de Python


Unittest.

 Test Loader (Cargador de Pruebas) – Es una clase de Python que carga casos de prueba y
suites creados localmente o desde una fuente de datos externa como un archivo. Libera un objeto
TestSuite que lleva los casos y suites.

 TestCase (Caso de Prueba) – La clase TestCase contiene los manipuladores de prueba y


proporciona ganchos para preparar cada manipulador y para limpiar después de la ejecución.
 Test Suite – Actúa como contenedor para agrupar los casos de prueba. Con la ayuda de una
suite de pruebas, puede combinar un conjunto de casos de prueba que representan funcionalidades
específicas de la aplicación bajo prueba.

 Test Runner – Proporciona una interfaz ejecutable para la ejecución de pruebas y entrega los
resultados al usuario. Puede utilizar una GUI, un medio textual o devolver un código estándar para
notificar los resultados de la ejecución de la prueba.

 TestReport (Reporte de Prueba) – Este componente organiza los resultados de la prueba,


muestra el estado de aprobado/no aprobado de los casos de prueba ejecutados. Incluso proporciona
los detalles de los pasos, el resumen de la ejecución global y el tiempo transcurrido en ejecución.

1.2. Prepare una Clase de Caso de Prueba para


Automatizar un Escenario.
Podemos crear una o más pruebas heredando la clase TestCase disponible en el
módulo Unittest. Para añadir un caso, también necesitamos proporcionar un método de
prueba correspondiente (un manejador) a la clase derivada. Para finalizar un caso de prueba,
podemos usar assert o cualquiera de sus variaciones para reportar el estado de prueba.

A continuación se presentan algunas de las funciones assert más comunes utilizadas casi en
todas las pruebas.

 Utilizar assertEqual () para verificar un resultado esperado.

 Utilizar assertTrue () para verificar una condición.

 Utilizar assertRaises () para verificar que se plantee una excepción esperada.

Además del manejador de pruebas, también podemos agregar rutinas como setUp
() y tearDown () para administrar la creación y disposición de cualquier objeto o condición
que sea obligatoria para una prueba.

Empecemos ahora a usar la biblioteca de pruebas de Unit y escribamos una prueba sencilla
heredando la clase TestCase. Para ello, necesitará importar el módulo <unittest> y definir
una clase que herede la clase TestCase.

Vea el código de abajo para tener una idea de la clase de prueba:

1. import unittest
2. from selenium import webdriver
3.
4. class SearchText(unittest.TestCase):
1.3. Uso del método setUp () para administrar los
requisitos previos de la prueba.
Un método <setUp ()> funciona como punto de entrada para los casos de prueba. Podemos
utilizarlo para ejecutar un conjunto fijo de acciones antes de ejecutar una prueba o todas las
pruebas definidas en la clase.

Estos son prerrequisitos que pueden incluir las siguientes tareas de preparación de la
configuración de pruebas.

1. Cree una instancia de un controlador de navegador.

2. Navegue a una URL base.

3. Datos de pruebas de carga para su ejecución.

4. Abra los archivos de registro para registrar entradas, estados y errores.

Este método no toma argumentos y no devuelve nada. Si un script tiene el método setUp
() definido, entonces el corredor lo llamará primero antes de ejecutar cualquiera de los
manejadores de prueba.

En nuestro ejemplo, estamos usando el método setUp () para crear una instancia de Firefox,
configurar las propiedades y navegar a la página principal de la aplicación antes de ejecutar
la prueba real.

1. import unittest
2. from selenium import webdriver
3.
4. class SearchText(unittest.TestCase):
5. def setUp(self):
6. # crea la sesion con firefox
7. self.driver = webdriver.Firefox(executable_path=r'C:\Users...añade tu ruta del... \geckodriver.exe')
8. self.driver.implicitly_wait(30)
9. self.driver.maximize_window()
10. # navega hasta esa url
11. self.driver.get("http://www.google.com/")
2. Empiece a escribir guiones de pruebas de
python selenium usando Unittest.
2.1. Crea tu primera prueba de selenium en Python con
Unittest.
Después de crear un método setUp (), ahora podemos escribir algunas pruebas para
verificar la funcionalidad de la aplicación. Así que, en primer lugar, definamos nuestro caso
de uso.

En este ejemplo, buscaremos un texto en google y verificaremos si la búsqueda devuelve una lista
de elementos.

Similar al <setUp ()> método, los métodos de prueba se implementan en la clase TestCase.
Al agregar estos métodos, es una buena práctica prefijar sus nombres con la prueba de
palabras. Tener tal nombre ayuda a Test Runner a distinguir entre una prueba y otros
métodos. Echa un vistazo al siguiente guión para demostrar el ejemplo dado de Python de
selenium.

1. import unittest
2. from selenium import webdriver
3.
4. class SearchText(unittest.TestCase):
5. def setUp(self):
6. # crea la nueva seccion del nagegador
7. self.driver = webdriver.Firefox(executable_path=r'C:\Users...añade tu ruta del... \geckodriver.exe')
8. self.driver.implicitly_wait(30)
9. self.driver.maximize_window()
10. # navega hasta la url
11. self.driver.get("http://www.google.com/")
12.
13. def test_search_by_text(self):
14. # obtener el cuadro de texto de búsqueda
15. self.search_field = self.driver.find_element_by_name("q")
16.
17. # escribe la palabra clave de búsqueda y la envía
18. self.search_field.send_keys("aprender python")
19. self.search_field.submit()
20.
21. #obtener la lista de elementos que se muestran después de la búsqueda
22. #actualmente en la página de resultados usando find_elements_by_class_namemethod
23.
24. lists = self.driver.find_elements_by_class_name("r")
25. no=len(lists)
26. self.assertEqual(10, len(lists))
2.2. Definir estrategia de limpieza a recursos
libres después de la ejecución de la prueba.
Una vez finalizada la ejecución de la prueba, hay que limpiar los prerrequisitos especificados
en el método setUp ().

Para lograr esto, la clase base TestCase proporciona otro método, por ejemplo, tearDown
() que el corredor llama después de la ejecución de la prueba. Nos permite limpiar los valores
inicializados al principio de la prueba mediante el método setUp ().

En nuestro ejemplo, cuando finaliza la ejecución de prueba, ya no necesitamos la instancia de


Firefox. Así que lo cerraremos en el método tearDown (), como se muestra en el siguiente
código.

1. import unittest
2. from selenium import webdriver
3.
4. class SearchText(unittest.TestCase):
5. def setUp(self):
6. # se crea la nueva seccion de firefox
7. self.driver = webdriver.Firefox(executable_path=r'C:\Users...añade tu ruta del... \geckodriver.exe')
8. self.driver.implicitly_wait(30)
9. self.driver.maximize_window()
10. # navaga hasta la url
11. self.driver.get("http://www.google.com/")
12.
13. def test_search_by_text(self):
14. # se obtiene el cuadro de busquedas
15. self.search_field = self.driver.find_element_by_name("q")
16.
17. # se escribe la plaabra clave y se submite
18. self.search_field.send_keys("aprender python")
19. self.search_field.submit()
20.
21. #obtener la lista de elementos que se muestran después de la búsqueda
22. #actualmente en la página de resultados usando find_elements_by_class_namemethod
23.
24. lists = self.driver.find_elements_by_class_name("r")
25. no=len(lists)
26. self.assertEqual(10, len(lists))
27.
28. def tearDown(self):
29. # close the browser window
30. self.driver.quit()
¿Cómo ejecutar el caso de prueba desde la línea
de comandos?
Ejecutar las pruebas desde la línea de comandos requeriría que agreguemos una llamada al
método main () en el script de prueba. También pasaremos un argumento al main ().
Aparecerán los detalles del resultado de los Test en la consola.

A continuación se muestra el código para facilitar la ejecución de la línea de comandos.


Tendremos que añadir éstas dos líneas de código justo al final.

1. if __name__ == '__main__':
2. unittest.main()

Cuando ejecutas el programa debería aparecer:

1. ----------------------------------------------------------------------
2. Ran 1 test in 7.081s
3.
4. OK

Si modificas la línea 26 por “self.assertEqual(11, len(lists))” tiene que salir un error como este
cuando ejecutes el código, ya que va a comprar 11 con 10 (los resultados de 1º pagina de
google siempre son 10):

1. len(lists)
2. F
3. ================================================================
======
4. FAIL: test_search_by_text (__main__.SearchText)
5. ----------------------------------------------------------------------
6. Traceback (most recent call last):
7. File "C:/Users/...selenium/11ejem.py", line 34, in test_search_by_text
8. self.assertEqual(11, len(lists))
9. AssertionError: 11 != 10
10.
11. ----------------------------------------------------------------------
12. Ran 1 test in 7.684s
13.
14. FAILED (failures=1)
Añada un TestCase más.
Hasta ahora, hemos automatizado un simple caso de prueba. Pero podemos añadir tantos
casos como se necesite en la clase TestCase. También ayudará a crear grupos lógicos de
pruebas relacionadas con una funcionalidad específica. Así que agreguemos otra prueba a la
clase TestCase. El nombre el nuevo método empieza con la palabra test, como se muestra en
el siguiente código.

1. def test_search_by_name(self):
2. # obtener el cuadro de texto de búsqueda
3. self.search_field = self.driver.find_element_by_name("q")
4. # se introduce la palabra clave y se submite
5. self.search_field.send_keys("Python class")
6. self.search_field.submit()
7. #obtener la lista de elementos que se muestran después de la búsqueda
8. #actualmente en la página de resultados usando find_elements_by_class_namemethod
9. list_new = self.driver.find_elements_by_class_name("r")
10. self.assertEqual(10, len(list_new))

Ejecutar el TestClass resultaría en abrir primero y luego cerrar las dos instancias de Firefox.
Así es como funcionan los métodos setUp () y tearDown () para cada método de prueba. A
continuación los resultados de los 2 Test:

1. ================================================================
======
2. FAIL: test_search_by_name (__main__.SearchText)
3. ----------------------------------------------------------------------
4. Traceback (most recent call last):
5. File "C:/Users/.../selenium/11ejem.py", line 45, in test_search_by_name
6. self.assertEqual(10, len(list_new))
7. AssertionError: 10 != 11
8.
9. ----------------------------------------------------------------------
10. Ran 2 tests in 14.740s
11.
12. FAILED (failures=1)
Refactoring setUp () y tearDown () Métodos de
optimización.
En los ejemplos anteriores, estábamos usando el método setUp () para crear instancias del
controlador Firefox. Pero este enfoque estaba conduciendo a la creación de una nueva
instancia del navegador web cada vez que se ejecutaba un nuevo caso de prueba.

Fue el método setUp () el que estaba causando este comportamiento mientras se ejecuta
antes de cada caso de prueba. El mismo caso es con el método tearDown () que dispara
para cada caso de prueba una vez finalizada la ejecución.

Así que podemos refactorizar nuestro script para minimizar el uso de recursos. Esto significa
que podemos compartir una única instancia de Firefox entre los métodos en lugar de crear
una nueva instancia cada vez.

Es posible utilizando los métodos setUpClass () y tearDownClass () junto con el


decorador @classmethod. Estos métodos nos permiten establecer los valores a nivel de
clase en lugar de a nivel de método. Los valores inicializados a nivel de clase se comparten
entre los métodos de prueba.

Veamos el ejemplo anterior con código modificado para llamar a los métodos setUpClass
() y tearDownClass ()con el decorador @classmethod. Ejemplo:
1. import unittest
2. from selenium import webdriver
3.
4. class SearchText(unittest.TestCase):
5. @classmethod
6. def setUp(self):
7. # se crea la nueva seccion de firefox
8. self.driver = webdriver.Firefox(executable_path=r'C:\Users...añade tu ruta del... \geckodriver.exe')
9. self.driver.implicitly_wait(30)
10. self.driver.maximize_window()
11. # va a la url
12. self.driver.get("http://www.google.com/")
13.
14. def test_search_by_text(self):
15. # se obtiene la caja de busquedas
16. self.search_field = self.driver.find_element_by_name("q")
17.
18. # se introduce la palabra clave y se submite
19. self.search_field.send_keys("aprender python")
20. self.search_field.submit()
21.
22. #obtener la lista de elementos que se muestran después de la búsqueda
23. #actualmente en la página de resultados usando find_elements_by_class_namemethod
24.
25. lists = self.driver.find_elements_by_class_name("r")
26. no=len(lists)
27. self.assertEqual(10, len(lists))
28.
29. def test_search_by_name(self):
30. # se obtiene la caja de busquedas
31. self.search_field = self.driver.find_element_by_name("q")
32. # se escribe la palabra clave y se submite
33. self.search_field.send_keys("Python")
34. self.search_field.submit()
35. #obtener la lista de elementos que se muestran después de la búsqueda
36. #actualmente en la página de resultados usando find_elements_by_class_namemethod
37. list_new = self.driver.find_elements_by_class_name("r")
38. self.assertEqual(10, len(list_new))
39.
40. @classmethod
41. def tearDown(self):
42. # se cierra la venta del navegador
43. self.driver.quit()
44.
45.
46. if __name__ == '__main__':
47. unittest.main()

Al ejecutar la prueba, podemos ver que ambas pruebas se están ejecutando en el mismo
navegador Firefox.
Assertions/Afirmaciones en el Unittest
Framework de Python
La clase TestCase de la biblioteca Python Unittest implementa una lista de métodos assert.
Podemos utilizarlos para hacer coincidir los valores reales devueltos por la aplicación con los
valores esperados. Con cada método, podemos especificar una condición que debe ser
verdadera para seguir ejecutando la prueba.

Los siguientes tres tipos de assert/afirmación están disponibles.

1. Comprobar equivalencia.
2. Comparación lógica.
3. Actuar en caso de Excepciones.

Mientras se ejecuta un test, la ejecución se mueve a la siguiente línea sólo si la aserción dada
pasa. De lo contrario, la prueba se detendría inmediatamente y aparecería un mensaje de
fallo.

Veamos una lista importante de métodos de afirmación.

Lista de métodos de afirmación en el módulo Python Unittest:

Assert Método Test Condición Sumario

Compruebe si “a” y “b” coinciden o no.


assertEqual(a, b
a==b También puede pasar un mensaje de
[,msg])
error.

assertNotEqual(a,b[, ejemplo
a!=b
msg]) assertEqual(element.text,”10″)

Verificar si la expresión dada evalúa


assertTrue(x[,msg])) bool(x) is True
Verdadero o Falso.
ejemplo
assertFalse(x[,msg])) bool(x) isFalse
assertTrue(element.is_displayed())

assertIsNot(a,
a no es b
b[,msg]))

fun(*args,**kwds) Compruebe si el paso de prueba sube


la Excepción específica mencionada.
assertRaises(exc, Un ejemplo de ello es utilizar este
fun,*args, **kwds) raises exc método para comprobar
<NoSuchElementFoundexception>.

assertRaisesRegex
p(exc, fun(*args,**kwds)rais
es excand
r, fun, *args, themessagematchesre
**kwds) gex r

Compara los valores numéricos


assertAlmostEqual(a
round(a-b,7) == 0 después de redondearlos con el
, b)
número del segundo argumento.

assertNotAlmostEqu
round(a-b,7) != 0
al(a,b)

assertGreater(a, b) a>b

assertGreaterEqual(
a>=b
a,b)

assertRegexpMatche Verifique si una búsqueda repetida


r.search(s)
s(s, r) coincide con el texto.

assertNotRegexpMat
not r.search(s)
ches(s, r)

Este método es una extensión del


assertMultiLineEqual
strings assertEqual (), diseñado para cadenas
(a, b)
multilíneas.

Este método verifica si las listas “a” y


assertListEqual(a, b) listas “b” coinciden. Ayuda a trabajar con los
campos desplegables.

fail() Este método falla la prueba


incondicionalmente. Permite la
creación de bloques condicionales
personalizados.

Cree una Test suite con Selenium


utilizando Unittest.
El módulo Unittest tiene una clase TestSuite que facilita la creación de un conjunto de
pruebas de punto a punto de Selenium Python Test Suite. Con esta característica, podemos
combinar varias pruebas en grupos lógicos y convertirlas en una suite de pruebas unificada.
Todo esto es posible usando las clases TestSuite, TestLoader y TestRunner.

Antes de entrar en detalles de TestSuite, agreguemos una nueva prueba para revisar la
página de inicio de la aplicación en prueba. Agregaremos esta prueba junto con las pruebas
de búsqueda anteriores en un solo conjunto de pruebas, como se muestra en el siguiente
código:

Agrupe los casos de prueba en una suite de


pruebas:
Ahora habrías entendido muy bien que usaremos la clase TestSuite para definir y ejecutar el
conjunto de pruebas. Y podemos agregar múltiples casos de prueba en él. Además, aparte de
la clase TestSuite, necesitamos usar las clases TestLoader y TextTestRunner para crear y
ejecutar una suite de pruebas. Consulte el siguiente código.

1. import unittest
2. from SeleniumPythonRefactorTestCase import SearchText
3. from SeleniumPythonMultipleTests import HomePageTest
4.
5. # se obtienen los test desde SearchText y la clase HomePageTest
6. search_text = unittest.TestLoader().loadTestsFromTestCase(SearchText)
7. home_page_test = unittest.TestLoader().loadTestsFromTestCase(HomePageTest)
8.
9. # se crea el pack de test combinando search_text y home_page_test
10. test_suite = unittest.TestSuite([home_page_test, search_text])
11.
12. # se ejecuta el pack de test
13. unittest.TextTestRunner(verbosity=2).run(test_suite)
Ejecute la suite de test
La clase TestLoader lee todos los métodos de prueba de los archivos de prueba
especificados que contienen la definición del conjunto de pruebas. A continuación, la
clase TestRunner toma el control del conjunto de pruebas y ejecuta todas las pruebas
especificadas. A continuación se muestra el comando para ejecutar el nuevo script de la suite
de pruebas.

Para ejecutar todo necesitas los dos códigos antes mencionados:

 SeleniumPythonRefactorTestCase

 SeleniumPythonMultipleTests

Después tener estos dos códigos (son lo que estan mas arriba de este post) creo otro archivo
y copia el código de Agrupe los casos de prueba en una suite de pruebas y ejecútalo. Esto
ejecutará todas las pruebas de las clases SearchText y HomePage y generará una salida
similar a esta:

======================================================================
FAIL: test_search_by_name (SeleniumPythonRefactorTestCase.SearchText)
———————————————————————-
Traceback (most recent call last):
File “C:\Users\……\selenium\SeleniumPythonRefactorTestCase.py”, line 46, in
test_search_by_name
self.assertEqual(10, len(list_new))
AssertionError: 10 != 11

———————————————————————-
Ran 5 tests in 68.177s

FAILED (failures=1, errors=2)


Generar Informe de Ejecución de HTML
Test Suite.
De forma predeterminada, la biblioteca Python Unittest emite la salida de prueba en la
consola terminal. Si desea compartir los resultados con la administración y las partes
interesadas, enviar los registros de la consola no es la forma adecuada.

Así que necesitas generar un informe que parezca presentable y profesional. Un informe
resumido con un buen formato, con un acceso detallado a los detalles es lo que se requiere.

Puesto que la biblioteca de pruebas de unidad no tiene la capacidad de producir tal informe,
por lo que debe utilizar la extensión HTMLTestRunner.

Para descargar el HTMLTestRunner, por favor siga el siguiente enlace.

Para integrar HTMLTestRunnersupport en nuestro script de prueba, necesitamos crear un


archivo de salida para almacenar el informe actual, configurar las opciones de
HTMLTestRunner, y ejecutar las pruebas de la siguiente manera.
Ejemplo de un Test suite en python con selenium:

1. import unittest
2. import HTMLTestRunner
3. import os
4. from SeleniumPythonRefactorTestCase import SearchText
5. from SeleniumPythonMultipleTests import HomePageTest
6.
7. # obtener la ruta del directorio al archivo de informe de salida
8. dir = os.getcwd()
9.
10. # se obtienen los test desde SearchText y la clase HomePageTest
11. search_text = unittest.TestLoader().loadTestsFromTestCase(SearchText)
12. home_page_test = unittest.TestLoader().loadTestsFromTestCase(HomePageTest)
13.
14. # se crea el pack de test combinando con search_text and home_page_test
15. test_suite = unittest.TestSuite([home_page_test, search_text])
16.
17. # abre el archivo de reporte
18. outfile = open(dir + "\SeleniumPythonTestSummary.html", "w")
19.
20. # configura las opciones de HTMLTestRunner
21. runner = HTMLTestRunner.HTMLTestRunner(stream=outfile,title='Test Report', description='Acceptance
Tests')
22.
23. # ejecuta la suite usando HTMLTestRunner
24. runner.run(test_suite)

Vous aimerez peut-être aussi