Korpi delfin
Les comparto el código ya con documentación.
Assertions
import unittest from selenium import webdriver #sirve como excepción para los assertions cuando queremos #validar la presencia de un elemento from selenium.common.exceptions import NoSuchElementException #ayuda a llamar a las excepciones que queremos validar from selenium.webdriver.common.by import By class AssertionsTest(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome(executable_path = r'.\chromedriver.exe') driver = self.driver driver.implicitly_wait(30) driver.maximize_window() driver.get("http://demo.onestepcheckout.com/") def test_search_field(self): self.assertTrue(self.is_element_present(By.NAME, 'q')) def test_language_option(self): self.assertTrue(self.is_element_present(By.ID, 'select-language')) def tearDown(self): self.driver.quit() #para saber si está presente el elemento #how: tipo de selector #what: el valor que tiene def is_element_present(self, how, what): try: #busca los elementos según el parámetro self.driver.find_element(by = how, value = what) except NoSuchElementException as variable: return False return True
Search tests
import unittest from pyunitreport import HTMLTestRunner from selenium import webdriver class SearchTests(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome(executable_path = r'.\chromedriver.exe') driver = self.driver driver.implicitly_wait(30) driver.maximize_window() driver.get("http://demo.onestepcheckout.com") def test_search_tee(self): driver = self.driver search_field = driver.find_element_by_name('q') search_field.clear() #limpia el campo de búsqueda en caso de que haya algún texto. search_field.send_keys('tee') #simulamos la escritura del teclado para poner "tee" search_field.submit() #envía los datos ('tee') para que la página muestre los resultados de "tee" def test_search_salt_shaker(self): driver = self.driver search_field = driver.find_element_by_name('q') search_field.send_keys('salt shaker') #escribimos 'salt shaker' en la barra de búsqueda search_field.submit() #envíamos la petición #hago una lista de los resultados buscando los elementos por su Xpath. Es la forma más rápida. products = driver.find_elements_by_xpath('//*[@id="top"]/body/div/div[2]/div[2]/div/div[2]/div[2]/div[3]/ul/li/div/h2/a') #vamos a preguntar si la cantidad de resultados es igual a 1 self.assertEqual(1, len(products)) def tearDown(self): self.driver.quit()
Smoke tests
from unittest import TestLoader, TestSuite from pyunitreport import HTMLTestRunner #para generar el reporte from assertions import AssertionsTest from search_tests_assertions import SearchTests assertions_test = TestLoader().loadTestsFromTestCase(AssertionsTest) search_tests = TestLoader().loadTestsFromTestCase(SearchTests) #contruimos la suite de pruebas smoke_test = TestSuite([assertions_test, search_tests]) #para generar los reporters kwargs = { "output": 'smoke-report' } #la variable runner almacena un reporte generado por HTMLTestRuner #usa como argumento "kwarsp" runner = HTMLTestRunner(**kwargs) #corro el rurner con la suite de prueba runner.run(smoke_test)
Andrés Corral
gracias
Gabriel Martin Estrada
Muchas gracias!!!!
Facundo Soto
No me gusta ser el negativo pero este curso me parece desastroso, está lleno de cosas no explicadas o implícitas o también cosas esenciales explicadas de manera vaga
Mario Alberto Treviño
Justo entre a los comentarios para ver si era impresión mía o si esta muy mal explicado.
Fredy Alexander Izquierdo Dominguez
Pienso igual.
Andrés Xavier Vargas Vera
Al parecer el código que muestra el profesor no guarda los reportes de los test cases, cuando se evalúan en un Suite, porque solo guarda el reporte del último Test Case....
Yo logré solucionarlo, al parecer hay que instalar otra librería, la librería que nos hace instalar el profesor al parecer es un fork de esta otra librería que tiene muchas mas funcionalidades y está actualizada constantemente.
pip install html-testRunner
https://github.com/oldani/HtmlTestRunner
Esta otra librería se importa: ANTES:
from pyunitreport import HTMLTestRunner
AHORA:
from HtmlTestRunner import HTMLTestRunner
y cuando se prueba Test Cases es igual que antes, no mas que ahora guarda los archivos con un mobre raro, si alguien logra descubrir como evitar esto, estaría agradecido:
Un pequeño cambio, en output, para guardar en carpetas destro de reports, se agrega esto:
El add_timestamps es para agregar la fecha y hora al nombre del archivo, no me gustó, por eso le pongo FALSE, pero si desean le pueden dejar TRUE
En cuanto para Suites, resuelve el problema que están teniendo: Lo unico que cambia son los kwargs y los imports dados anteriormente
kwargs = { "output": "reports/smoke-report", "report_name": "smoke-report", "combine_reports": True, "add_timestamp": False } # ? create runner with the parameters and run runner = HTMLTestRunner(**kwargs) runner.run(smoke_test)
En este caso el nombre del archivo si se guarda con el nombre que se le da
Y ahora se crea un solo reporte para todos los test cases en el suite
Tomas Jesus Escobar Cueltan
Muchas gracias amigo por tomarte el tiempo de explicar esta parte, muy importante saberlo.
Jesús Enrique Morocoima Marcano
Super
Pablo Rivera Sepúlveda
El tema de automatizacion es increible... lastima la explicacion de este curso, que desastre!!!
Manuel Rodrigo Zamorano Jimenez
Así es ..!
Julian Crispin
Este curso es de los peores, enredado, dificil de seguir, una pesadilla
Carlos Andres Ocampo Pabon
Para los que no entendimos el porqué se el doble asterisco cuando se está pasando el **kwargs al HTMLTestRunner, aquí dejo un articulo donde explican:
Explicación **kwargs
Cesar Sosa
Heroe, gracias! ya entendí mejor el código de esta clase.
David Rodriguez
Excelente Clase Héctor, Esto es súper útil para no hacer múltiples ejecuciones. Interesante que al no agregar el campo report_name se guarda con el dia y hora de la ejecución.
David Diaz
Buenas noches, compañeros! Si en algún momento alguien llegase a tener problema con:
Les traigo la solución a ambos.
Assertions
import unittest from selenium import webdriver from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.common.by import By from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager class AssertionsTest(unittest.TestCase): @classmethod def setUp(self): self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) driver = self.driver driver.implicitly_wait(30) driver.maximize_window() driver.get("Platzi decía que el sitio no era seguro.com") def test_search_field(self): print('Searching the search bar') self.assertTrue(self.is_element_present(By.NAME, 'q')) def test_language_option(self): print('Searching the Select language dropdown') self.assertTrue(self.is_element_present(By.ID, 'iselect-language')) @classmethod def tearDown(self): self.driver.quit() def is_element_present(self, how, what): try: self.driver.find_element(by=how, value=what) except NoSuchElementException(): self.driver.close() return False return True
(Ojo, lo deje como "iselect-language" para que vean que ejecuta el código completa aún cuando algún elemento no exista)
Search Test
import unittest from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from webdriver_manager.chrome import ChromeDriverManager class SearchTests(unittest.TestCase): @classmethod def setUp(self): self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) driver = self.driver driver.implicitly_wait(30) driver.maximize_window() driver.get("Platzi no dejo poner el URL :c") def test_search_tee(self): driver = self.driver search_field = driver.find_element(By.NAME, "q") search_field.clear() search_field.clear() search_field.send_keys('tee') search_field.submit() def test_search_salt_shaker(self): driver = self.driver search_field = driver.find_element(By.NAME, "q") search_field.clear() search_field.send_keys('salt shaker') search_field.submit() #Searching by XPATH -> $x('//div[@class = "product-info"]/h2[@class="product-name"]/a/text()').map(x => x.wholeText) or $x('//div[@class = "product-info"]/h2/a/text()').map(x => x.wholeText) # REMEMBER: "h2" could also be replaced by "text-fill" products = driver.find_elements(By.XPATH, '//div[@class = "product-info"]/h2[@class="product-name"]/a') self.assertEqual(1, len(products)) @classmethod def tearDown(self): self.driver.quit()
Finalmente... Smoke Tests
from unittest import TestLoader, TestSuite from assertions import AssertionsTest from searchtests import SearchTests from HtmlTestRunner import HTMLTestRunner assertions_test = TestLoader().loadTestsFromTestCase(AssertionsTest) search_tests = TestLoader().loadTestsFromTestCase(SearchTests) #contruimos la suite de pruebas smoke_test = TestSuite([assertions_test, search_tests]) # Aquí generamos nuestros reportes kwargs = { "output": "reports/smoke-report", "report_name": "smoke-report", "combine_reports": True, "add_timestamp": True } runner = HTMLTestRunner(**kwargs) runner.run(smoke_test)
Como pueden notar, la sección importante es la sección de "kwargs", aquí usamos "combine_reports": True para que los 4 reportes puedan estar juntos. Espero esto les ayude y así evitan horas de busquedas para solucionar esos problemas.
Gracias por sus atenciones y HAPPY CODING!
Jose Leonardo Araya Parajeles
como lograste hacer funcionar el: from HtmlTestRunner import HTMLTestRunner he buscado pero no logro instalarlo
Eduardo Pérez
Hola Jose, que error te esta saliendo?
Julio César Zaravia Paredes
¡Hola Comunidad! . En un video anterior dejé una respuesta con una explicación sobre este error 👇👇👇 .
Sergio Bryan Madrid Nuñez
Puedes utilizar el WebDriver de Firefox. https://pythonbasics.org/selenium-firefox/, aquí pueden encontrar un blog que explica como hacerlo. En lugar de instalar el webdriver de chrome, hay que utilizar algo similar llamado geckodriver que pueden descargar aquí: https://github.com/mozilla/geckodriver/releases, sólo dejan el archivo descomprimido en el mismo nivel en el que tengan su código o señalan la ruta del geckodriver como hacemos en el curso. Ahora seria: webdriver.Firefox()
Sebastián Franco
A mi tambien me daba el error de USB, pero era porque en la función test_lenguage_option() el assert de lenguaje tenía escrito "select-lenguage" en vez de "select-language", fue corregirlo y todo fluyó. Puede que a alguien más le sirva.
Ricardo Moreno
*Actualización Para el día de hoy ya no aparece el item de Language por lo tanto es test falla en esa parte
Saludos!
Julian Ramirez Chacon
A día de hoy select-language si sirve, la prueba pasa sin ningún problema
Ricardo Moreno
Gracias por la info, al momento que realicé el curso no pasaba el test y era porque no estaba la opcion del lenguaje... supongo que no lo vi o algo cambio jaja.
Saludos!
Juan Francisco Pons
Es un quilombo esta clase! Pésimo todo. Salta de la nada a otro archivo con el mismo nombre pero distinto contenido.
Manuel Rodrigo Zamorano Jimenez
Asi es ..
Agustin Zamar
Hola! Cuando se genera el reporte de la suite de tests smoketests solo muestra reportes de los tests del ultimo archivo ejecutado. ¿Hay alguna forma de que el reporte incluya a todos los tests? ¿O que se cree un archivo para cada uno?
Gabriel Ichcanziho Pérez Landa
tengo exactamente el mismo problema :( y al parecer no soy el único
Víctor Mazo
La única forma que encontré fue ingresar cada test de forma separada en el TestSuite(), sin notación de lista, más creo que se pierde la ventaja de utilizar el test suite.
Boris Saavedra
El profe no lo mencionó, pero si corren el Test Suite y colocan el parámetro report_name los reportes (obviamente) se sobrescriben y solo verán un reporte. Es por eso que conviene no colocar este parámetro.
De nada 🤣
Alejandro Benjamín Like García
aunque no coloques el report_name se siguen sobrescribiendo. figuran con la misma hora y segundo
Felipe Alexis Moreno Durán
Estimados el codigo a continuación:
assertions.py
import unittest from selenium import webdriver from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.common.by import By class AssertionsTest(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome(executable_path = r'C:\Python Scripts\curso_selenium\chromedriver.exe') driver = self.driver driver.implicitly_wait(30) driver.maximize_window() driver.get("http://demo-store.seleniumacademy.com/") def test_search_field(self): self.assertTrue(self.is_element_present(By.NAME, 'q')) def test_language_option(self): self.assertTrue(self.is_element_present(By.ID, 'select-language')) def tearDown(self): self.driver.quit() def is_element_present(self, how, what): try: self.driver.find_element(by = how, value = what) except NoSuchElementException as variable: return False return True``` searchtests.py
import unittest from pyunitreport import HTMLTestRunner from selenium import webdriver
class SearchTests(unittest.TestCase):
def setUp(self): self.driver = webdriver.Chrome(executable_path = r'C:\Python Scripts\curso_selenium\chromedriver.exe') driver = self.driver driver.implicitly_wait(30) driver.maximize_window() driver.get("http://demo-store.seleniumacademy.com/") def test_search_tee(self): driver = self.driver search_field = driver.find_element_by_name('q') search_field.clear() search_field.send_keys('tee') search_field.submit() def test_search_salt_shaker(self): driver = self.driver search_field = driver.find_element_by_name('q') search_field.send_keys('salt shaker') search_field.submit() products = driver.find_elements_by_xpath('//*[@id="top"]/body/div/div[2]/div[2]/div/div[2]/div[2]/div[3]/ul/li/div/h2/a') self.assertEqual(1, len(products)) def tearDown(self): self.driver.quit()```
smoketests.py
from unittest import TestLoader, TestSuite from pyunitreport import HTMLTestRunner from assertions import AssertionsTest from searchtests import SearchTests assertions_test = TestLoader().loadTestsFromTestCase(AssertionsTest) search_tests = TestLoader().loadTestsFromTestCase(SearchTests) #Construccion de suite de pruebas smoke_test = TestSuite([assertions_test, search_tests]) #Respecto a los reportes kwargs = { "output": 'smoke-report' } runner = HTMLTestRunner(**kwargs) runner.run(smoke_test)``` Exito y saludos
John Steven González
Cuando se utiliza el decorador @classmethod la prueba dura muchísimo menos, hablando en tiempo.
Leslie Paz Ore
Una consulta compañeros, aún no comprendo bien cuál es la funcionalidad de
verbosity=2
Podrían ayudarme, please?
Miguel Andres Rendon Reyes
Hola Leslor, te explico brevemente, que la función del parámetro verbosity es para definir, qué tantas explicaciones queremos por parte de unittest. Es decir, qué tanto texto quieres que aparezca en medio de la prueba. Puedes probar poner 1 y verás cómo casi no te va a decir nada en la terminal. Es como si con verbosity, le pides que sea verbal, que explique más detalladamente.
Leslie Paz Ore
Muchas Gracias Umi! , Realize el cambio de verbosity a 1, pero me salen las mismas lineas que cuando le pongo 3 o 4, Supongo que mientras más complejo sea el Test Case, lograré ver la diferencia. Thanks! :)
Jessica Martinez Freire
No se por que, pero el xpath aparentemente cambió y colocando (1, len (products)) no da, sale AssertionError: 1 != 0.
Mi xpath sale: '//*[@id="top"]/body/div/div[2]/div[2]/div/div[2]/div[1]/div[4]/ul/li/div/h2/a'
Y el xpath del video sale: '//*[@id="top"]/body/div/div[2]/div[2]/div/div[2]/div[2]/div[3]/ul/li/div/h2/a'
¿Como me doy cuenta en este caso? porque la logica esta bien, pero copio el xpath de la pagina y no me da (hoy por hoy), pero si uso el xpath del video si me da.
< def test_search_salt_shaker(self): driver = self.driver search_field = driver.find_element_by_name('q') search_field.send_keys('salt shaker') search_field.submit() products = driver.find_elements_by_xpath('//*[@id="top"]/body/div/div[2]/div[2]/div/div[2]/div[2]/div[3]/ul/li/div/h2/a') self.assertEqual(1, len(products))>
Julian Ramirez Chacon
Tienes mal la ruta XPATH , la ruta es:
products = driver.find_elements_by_xpath('/html/body/div/div[2]/div[2]/div/div[2]/div[2]/div[3]/ul/li/div/h2/a')
Angela Nipitella
Me pasaba lo mismo. Resulta que cuando le daba a inspeccionar la pagina cambiaba de tamaño poder desplegar el menú de desarrolladores de chrome. Al copiar el xpath lo estaba haciendo en una vista adaptada para móviles. esto lleva a tu portapapeles un xpath diferente al de una vista para monitor de pc. Lo pude solucionar en el menú de opciones de la consola de desarrolladores de chrome para que al darle al botón de inspeccionar se abra esta consola en una ventana nueva, dejando intacto el tamaño original de la web.
Miguel Rodriguez Perez
Este curso es maravilloso para el que tiene cierto nivel en python, si eres nuevo tomando el curso y no tienes experiencia resolviendo los problemas mas comunes al programar y buscar documentación probablemente se te complique un poco mas de lo habitual y creas que se tiene que estar explicando todo lo que escribe el profesor.
Luis Jhonayquer Zapata Yamo
Al parecer Selenium a la hora de ejecutar los test lo hace en función al orden alfabético según del nombre las funciones de los test.
Karla Berenice
Hola, saben como se le puede hacer para que se genere un solo archivo de resultados con todos los casos de prueba de todas las clases, es que conmigo me genera uno, pero solo de la última clase ejecutada
Agustin Zamar
Hola! ¿Pudiste encontrar alguna solucion a esto?
Andrés Xavier Vargas Vera
Yo logré solucionarlo al parecer hay que instalar otra librería, la librería que nos hace instalar el profesor al parecer es un fork de esta otra librería que tiene muchas mas funcionalidades y está actualizada constantemente.
pip install html-testRunner
https://github.com/oldani/HtmlTestRunner
Esta otra librería se importa: ANTES:
from pyunitreport import HTMLTestRunner
AHORA:
from HtmlTestRunner import HTMLTestRunner
y cuando se prueba Test Cases es igual que antes, no mas que ahora guarda los archivos con un mobre raro, si alguien logra descubrir como evitar esto, estaría agradecido:
Un pequeño cambio, en output, para guardar en carpetas destro de reports, se agrega esto:
El add_timestamps es para agregar la fecha y hora al nombre del archivo, no me gustó, por eso le pongo FALSE, pero si desean le pueden dejar TRUE
En cuanto para Suites, resuelve el problema que están teniendo: Lo unico que cambia son los kwargs y los imports dados anteriormente
kwargs = { "output": "reports/smoke-report", "report_name": "smoke-report", "combine_reports": True, "add_timestamp": False } # ? create runner with the parameters and run runner = HTMLTestRunner(**kwargs) runner.run(smoke_test)
En este caso el nombre del archivo si se guarda con el nombre que se le da
Y ahora se crea un solo reporte para todos los test cases en el suite
jesus alberto negrin guerrero
Excelente tema y profesor, de hecho justo un error que comento cuando buscamos el xpath que es poner (elements) plural valga la redundancia casi se me explotaba la cabeza porque lo buscaba en singular y me arrojaba un error lo lei como 3 veces hasta que me di cuenta por el siemple hecho de no prestar atencion XD
Héctor Daniel Vega Quiñones
ProfesorMuchas gracias por el comentario, Jesús. En efecto hay que estar muy atentos cuando queremos identificar uno o varios elementos :eyes: