Crear un virtual environment: python3.10 -m venv ~/venvs/frameworkenv
Acceder al framework: cd ~/venvs/frameworkenv/bin
Activar framework: source activate
Desactivar framework: deactivate
Dentro del framework se debe acceder a la carpeta donde se tienen los archivos de pruebas
Para poder correr pruebas, instalamos pytest: pip install pytest
Corremos pytest para correr las pruebas: pytest
- Para que pytest reconozca funciones como casos de prueba, deben tener un nombre que comience con "test_"
- Para correr los tests de un directorio en particular: pytest directory/subdirectory
- Para obtener información más detallada utilizamos verbose: pytest -v
- Para mostrar los standard out por linea de consola incluso en casos de éxito, se debe agregar -s al comando para correr los tests: pytest -s
- Para poder usar selenium y webdriver debemos instalar selenium y webdriver_manager: 'pip install selenium' y luego 'pip install webdriver-manager'. (o agregar los diferentes drivers directamente al PATH)
- Cuando una función de caso de prueba pasa con éxito, suele identificarlo con un punto .
- Cuando una función de caso de prueba falla, suele identificarlo con la letra F
- Para poder ver que paquetes tengo instalado en un ambiente: pip list
- Para configurar pytest se puede utilizar el archivo pytest.ini
- Para configurar el proyecto para usar diferentes environments se puede utilizar el archivo config.py con funciones inicializadoras que luego utilizamos desde el archivo conftest.py con el uso de 'parser'
- Si se definen textos de help, las opciones customizadas se mostrarán en pytest -h
Se pueden configurar marcadores en pytest.ini y utilizar en las diferentes pruebas. Para listar todos los marcadores registrados: pytest --markers Para correr solo las pruebas de un marcador: pytest -m marker_name Para correr las pruebas de varios marcadores: pytest -m "marker_name or another_marker" Para correr las pruebas que tienen varios marcadores a la vez: pytest -m "marker_name and another_marker" Para correr todas las pruebas excepto las de un marcador: pytest -m "not marker_name" para correr un test de browser de manera interactiva se puede comenzar en un archivo .py y ejecutarlo con "python -i path_to_file"
Se pueden marcar las clases, lo que implicará que todos los métodos de esas clases tendrán el mismo marcador
Los fixtures se definen en el archivo conftest.py y se pueden utilizar desde cualquier archivo en la carpeta donde se encuentre y las subcarpetas de la misma Los fixtures pueden manejar su propio teardown, utilzando la palabra clave 'yield', todo lo que se defina después son las actividades de teardown Los fixtures son llamados cuando son usados (como argumento de una función), por lo que definir una función dentro de un fixture permite atrasar el momento de llamado de la función interna Un fixture puede tener los siguientes scopes:
- function: usa una unica instancia por función, sin importar cuantas veces se lo llame. Es el valor por defecto en caso de que no se defina un scope
- session: usa una unica instancia en la totalidad de la sesión de testeo
- class: corre una vez por clase
- module: corre una vez para un modulo
- package
Para generar reportes en un archivo html instalamos pytest-html: pip install pytest-html Para generar un reporte corremos las pruebas indicando el nombre del archivos a generar: pytest --html="results.html"
Para generar reportes xml corremos las pruebas indicando el nombre del archivo a generar: pytest --junitxml="results.xml"
-- To Do --
Se puede usar el marcador skip para saltar una prueba: @mark.skip Se puede definir una razón para skipear una prueba: @mark.skip(reason="XX") y se puede leer con las opciones '-rs' para leer (read) los skips
Para definir un caso de prueba que se espera que falle, se usa el marcador xfail: @mark.xfail Se puede definir una razón para esperar una falla: @mark.xfail(reason="XX") y se puede leer con '-rx'
Podemos definir parámetros para una función de testeo con el marcador parametrize, definiendo el nombre del parametro y los posibles valores, y de esta forma la funcion se ejecutará 1 vez por cada parámetro También podemos definir parámetros para un fixture, en ese caso se ejecutará la función que haga uso del fixture 1 vez por cada parámetro del mismo
Podemos usar la librería pytest-xdist: pip install pytest-xdist De esta manera podemos definir el numero de threads a utilizar durante los tests. Por ejemplo para 4 threads: pytest tests/parallel -n4 Es importante que los tests sean modulares y no dependientes de otros tests para que no interfieran con el uso de memoria Tambien podemos delegar la selección del número de threads de forma automática: pytest tests/parallel -nauto
Instalamos selenium: pip install selenium Instalamos también los drivers de los navegadores que utilizaremos. Debemos recordar agregar el directorio en el que se encuentran los drivers al PATH
- Entramos a la consola de python: python
- Import del webdriver: from selenium import webdriver
- Definimos un browser: browser = webdriver.Chrome()
- Accedemos a una pagina: browser.get("https://techstepacademy.com/training-ground")
- Podemos guardar el path del elemento en una variable auxiliar: input1Path = "input[id='ipt1']"
- Import del By: from selenium.webdriver.common.by import By
- Encontramos el elemento: input1Element = browser.find_element(By.CSS_SELECTOR, input1Path)
- Enviamos modificaciones: input1Element.send_keys("Automated input content")
- Se pueden utilizar con By.CSS_SELECTOR
- Desde la consola del inspector podemos probar selectores CSS con: $$("selector CSS")
- Selector por id: input#ipt1 ó input[id='ipt1']
- Se pueden utilizar con By.XPATH
- Desde la consola del inspector podemos probar xpath con: $x("camino hacia elemento")
- Ejemplos: //button[@name='butn1'], //b[contains(text(), 'Product 1')]/../../p
- ID = "id"
- XPATH = "xpath"
- LINK_TEXT = "link text"
- PARTIAL_LINK_TEXT = "partial link text"
- NAME = "name"
- TAG_NAME = "tag name"
- CLASS_NAME = "class name"
- CSS_SELECTOR = "css selector"
Utilizar import time; time.sleep(x); no es la manera más optima de realizar esperas, ya que espera un tiempo determinado y no a una condición determinada. Para esperar por una condicion determinada se utilizan las librerías selenium.webdriver.support.wait y selenium.webdriver.support.expected_conditions en conjunto.
Se puede acceder a un iFrame con: browser.switch_to.frame(iframeElement) Y volver a la pagina origen con: browser.switch_to.default_content()
Los Page Objects son clases que permiten:
- Describir porciones útiles de una página, de manera legible
- Manipular elementos de una página
- Visualizar información útil sobre el estado actual de una página
- Crear una capa de abstracción para manejar una página
- Evitar duplicación de código para manejar browsers, paginas y elementos
Se puede definir una funcion con @property para llamarlas como propiedad en lugar de como funciones. Las propiedades permiten el "lazy loading", por lo que siempre intenta tomar los elementos en tiempo real.
Requerimientos: tener instalado lxml Utilizar arboles parseados con lxml es más rapido que utilizar selenium, ya que selenium constantemente accede a la pagina web mientras que el arbol se mantiene en memoria