Académique Documents
Professionnel Documents
Culture Documents
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.
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.
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.
A continuación se presentan algunas de las funciones assert más comunes utilizadas casi en
todas las pruebas.
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.
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.
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 ().
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.
1. if __name__ == '__main__':
2. unittest.main()
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.
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.
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.
assertNotEqual(a,b[, ejemplo
a!=b
msg]) assertEqual(element.text,”10″)
assertIsNot(a,
a no es b
b[,msg]))
assertRaisesRegex
p(exc, fun(*args,**kwds)rais
es excand
r, fun, *args, themessagematchesre
**kwds) gex r
assertNotAlmostEqu
round(a-b,7) != 0
al(a,b)
assertGreater(a, b) a>b
assertGreaterEqual(
a>=b
a,b)
assertNotRegexpMat
not r.search(s)
ches(s, r)
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:
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.
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
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.
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)