sábado, 23 de diciembre de 2017

Guía para utilizar WebElementHighlighter

WebElementHighlighter es una librería python que nos permite resaltar WebElements de Selenium. La principal finalidad de esta librería es poder mostrar al tester que elementos de una página están fallando.

Sus funcionalidades actuales son:

  • Hacer parpadear WebElements.
  • Cambiar estilos como fondo y bordes de WebElements.

Instalación.

pip install webelement_highlighter

Ejemplo de uso.

from webelement_highlighter import WebElementHighlighter
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://www.w3schools.com/js/default.asp")

wh = WebElementHighlighter(driver)

we = driver.find_element_by_id("topnavbtn_references")
wes = driver.find_elements_by_class_name("w3-col")

wh.make_it_blink(we)
wh.make_them_blink(wes, times=20)

wh.highlight_element(we)
wh.highlight_elements(wes, stop=True)

Nota.

Para ejecutar el ejemplo es necesario tener instalada la librería selenium.

Enlaces.

Repositorio: https://github.com/rtorres90/webelement_highlighter

Guía para utilizar MaildropccReader.

MaildropccReader es un librería que permite extraer correos desde cuentas de www.maildrop.cc. Maildrop es una página que nos permite tener acceso a cuentas de correo públicas que usualmente se utilizan para probar si aplicaciones o servicios están enviando correos a terceros apropiadamente.

Instalación.


Para instalar MaildropccReader solamente debemos ejecutar el siguiente comando:

pip install MaildropccReader


Ejemplo de uso.

>>> from MaildropccReader import MaildropccReader
>>> maildrop_reader = MaildropccReader(email_account="chile")
>>> maildrop_reader.get_emails()
Output:
[{
    'id':'aTC7Qx',
    'sender': u'test@ismyemailworking.com',
    'subject':'IsMyEmailWorking.com - Test ID [c8a64c21-2c1b-463d-8bf0-1283f8e16f92]',
    'date': u'Jul 15 2017 10:30 AM',
    'body':'Received: from IsMyEmailWorking.com ([108.60.212.145])\r\n        by localhost\r\n        with SMTP (MailDrop) id J55KIM4A\r\n        for chile@maildrop.cc;\r\n        Sat, 15 Jul 2017 10:30:25 -0700 (PDT)\r\nMIME-Version: 1.0\r\nMessage-ID: <afe6e0fd7cfe899d@b0467bdd42a8d410>\r\nDate: Sat, 15 Jul 2017 10:30:58 -0700\r\nFrom: "Email Test" <test@ismyemailworking.com>\r\nTo: chile@maildrop.cc\r\nSubject: IsMyEmailWorking.com - Test ID [c8a64c21-2c1b-463d-8bf0-1283f8e16f92]\r\nContent-Type: text/plain;\r\n\tcharset="utf-8"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nCongratulations=20you=20have=20now=20proven=20that=20you=20at=20least=20rec=\r\neive=20email!=20Now=20to=20prove=20that=20you=20can=20also=20send=20email=\r\n=20simply=20reply=20to=20this=20message=20and=20we=20will=20let=20you=20kno=\r\nw=20when=20we=20receive=20your=20reply.=20Be=20sure=20to=20check=20your=20j=\r\nunk/bulk/spam=20(whatever=20it=20is=20for=20you)=20box=20again=20for=20our=\r\n=20next=20reply.=0d=0a=0d=0a=0d=0aPlease=20note,=20we=20do=20not=20spam=20o=\r\nr=20solicit=20anyone.=20You=20received=20this=20email=20because=20you=20(or=\r\n=20someone=20posing=20to=20be=20you)=20requested=20it.=20We=20implement=20a=\r\nnd=20work=20to=20constantly=20improve=20our=20security=20technologies=20in=\r\n=20order=20to=20prevent=20non-humans=20and=20others=20from=20using=20your=\r\n=20email=20address=20in=20our=20service=20while=20at=20the=20same=20time=20=\r\nothers=20may=20work=20constantly=20to=20defeat=20our=20security.=20If=20you=\r\n=20have=20received=20this=20email=20and=20did=20not=20request=20us=20please=\r\n=20contact=20us=20via=20the=20contact=20link=20on=20our=20website=20at=20ht=\r\ntp://IsMyEmailWorking.com/Contact.aspx.\r\n'
}]
Enlaces.
Repositorio: https://github.com/rtorres90/maildropcc-reader

sábado, 25 de noviembre de 2017

Utilizar eñes y tildes en Python.

Para poder utilizar eñes y tildes en nuestros scripts python, es necesario utilizar un tipo de 'coding' que soporte dichos caracteres. Si no especificamos que coding deseamos utilizar, python usará el coding ASCII de 7bits. La solución a este problema es añadir la siguiente linea al comienzo de los scripts donde se utilizarán las tildes o eñes.

# -*- coding: utf-8 -*-

Ejemplo de como implementar el coding.

# -*- coding: utf-8 -*-


print "Hola mundo! Ahora podrás utilizar eñes y tildes! yay"


Utilizando las strftime.

strftime es un método que podemos encontrar en objetos nativos de fechas como date, datetime y time. Con este método podemos especificar un formato de fecha personalizado y obtener como resultado un string de nuestro objeto con el formato esperado. Dicho formato debe ser entregado como una directiva (directivas disponibles con ejemplos).

Ejemplo:

from datetime import datetime

date1 = datetime(2011, 4, 23, 12, 22, 3)
date2 = datetime(2015, 1, 2, 8, 20, 13)

print date1.strftime("%b %d %Y %H:%M:%S")
>>> Apr 23 2011 12:22:03
print date2.strftime("%d del %m del año %Y")
>>> 02 del 01 del año 2015

sábado, 18 de noviembre de 2017

Directivas de formatos de fecha para utilizar con strftime y strptime.

Ejemplos basados en datetime.datetime(2013, 9, 30, 7, 6, 5)



Código Explicación Ejemplo
%a Día de la semana abreviado. Mon
%A Nombre completo de día de la semana. Monday
%w Número de la semana como dígito, donde 0 es Domingo y 6 es Sábado. 1
%d Día de la semana en número decimal, si contiene sólo un dígito python añadirá un cero a la izquierda. 30
%-d Día de la semana en número decimal. 30
%b Nombre de mes abreviado. Sep
%B Nombre completo de mes. September
%m Mes como número decimal,  si contiene sólo un dígito python añadirá un cero a la izquierda. 09
%-m Número decimal del mes. 9
%y Últimos dos dígitos del año,  si contiene sólo un dígito python añadirá un cero a la izquierda. 13
%Y Año en números decimales. 2013
%H Hora en números decimales, si contiene sólo un dígito python añadirá un cero a la izquierda. (Formato 24 horas) 07
%-H Hora en números decimales. (Formato 24 horas) 7
%I Hora en números decimales, si contiene sólo un dígito python añadirá un cero a la izquierda. (Formato 12 horas) 07
%-I Hora en números decimales. (Formato 12 horas) 7
%p Retorna si es AM o PM. AM
%M Minutos en número decimales, si contiene sólo un dígito python añadirá un cero a la izquierda. 06
%-M Minutos en número decimales. 6
%S Segundos en número decimales, si contiene sólo un dígito python añadirá un cero a la izquierda. 05
%-S Segundos en número decimales. 5
%f Microsegundos en números decimales, python añadirá un cero a la izquierda hasta tener 6 números. 000000
%Z Time zone.
%j Día del año en números decimales, python añadirá un cero a la izquierda hasta tener 3 números. 273
%-j Día del año en números decimales. 273
%U Número de la semana en números decimales,  si contiene sólo un dígito python añadirá un cero a la izquierda. 39
%W Número de la semana en números decimales. 39
%c Muestra la fecha y hora de la manera esperada para el formato local. Mon Sep 30 07:06:05 2013
%x Muestra la fecha de la manera esperada para el formato local. 09/30/13
%X Muestra la hora de la manera esperada para el formato local. 07:06:05
%% Caracter literal de  '%'. %

Fuente: http://strftime.org/

miércoles, 28 de junio de 2017

Creando data por defecto en django

Introducción.

Cuando te encuentras desarrollando una aplicación django, algunas veces es necesario poblar algunas tablas del proyecto con datos por defecto para nuestra aplicación, usualmente esto se utiliza para datos como tipos, países, código de área, usuarios, etc.

Para poder llevar esto a cabo utilizaremos el módulo migrations de django.

¡Manos a la obra!


Para demostrar como functiona esto,  nos pondremos en el caso de que estamos utilizando un proyecto django vacío. Por lo tanto ahora ejecutaremos el comando para crear una nueva app.

python manage.py startapp demo


Como se puede inferir actualmente tenemos un proyecto django con una aplicación llamada demo sin ningún modelo en él. Debido a esto, para poder demostrar como poblar datos por defecto haremos los cambios en la tabla Users la cual viene incluida en django. Antes de avanzar al siguiente paso,  recuerda añadir la app demo a la lista de INSTALLED_APPS en el archivo settings.py del proyecto.  Con esto terminado ejecutaremos este comando para crear un archivo de migración vacío.

python manage.py makemigrations --empty demo


Este comando nos generará un archivo como este en la carpeta migrations de la app demo.

from __future__ import unicode_literals

from django.db import migrations

class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
    ]
Ahora debemos aplicar los siguientes cambios para crear un usuario por defecto en la base de datos.

from __future__ import unicode_literals

from django.db import migrations

def create_test_user(apps, schema_editor):
    from django.contrib.auth.models import User
    User.objects.create_superuser('test', 'test@mailinator.com', 'test')


class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.RunPython(create_my_user),
    ]

Tal como podemos ver, hemos añadido una función para crear un usuario, luego en el arreglo operations pasamos esta función como un método que debe ser utilizado cuando el comando migrate sea ejecutado.

Ahora para ver los cambios efectuados, usaremos el comando migrate.

python manage.py migrate

¡Y listo!

Desde mi punto de vista esta es la manera más simple para añadir data por defecto a una base de datos, el hecho de poder utilizar código python para llevarlo a cabo esto nos da la posibilidad de insertar una cantidad gigante de data utilizando for loops y variables aleatorias.

Ahora es tu turno de utilizar esto ejemplo como base para un modelo de tu proyecto. Recuerda comentar si tienes dudas o sugerencias.

¡Hasta Pronto!

martes, 6 de junio de 2017

Configuración de webdriver para manejar descarga de PDFs.

Uno de los grandes problemas al momento de crear tests para una aplicación web que entregue PDFs como resultado en algunas de sus funcionalidades,  es controlar el comportamiento por defecto que tendrá el navegador frente a dichos archivos. Según mi experiencia como QA de automatización los principales problemas son los siguientes:

  • Ventanas de confirmación de descarga. ¡Un verdadero dolor de cabeza!, es imposible interactuar con ellas porque son parte del navegador y no de la página web.
  • Ubicación del archivo a descargar. Un gran problema si no es manejado en la configuración de tu driver porque el navegador por defecto intentará usar sus carpetas ocultas en los lugares más oscuros de tu pc, ten en cuenta que además las rutas para dichos directorios son diferentes por sistema operativo, por lo tanto buscar manualmente o hardcodear una ruta es casi imposible sin previa investigación.
  • Plugins por defecto del navegador. Actualmente los navegadores son capaces de leer los PDFs sin ningún tipo de plugin de terceros. Esto es un problema bastante recurrente, intentas descargar un pdf, pero ¡pum! el navegador mágicamente lo abre, rompiendo totalmente con el flujo de tu test.


Para poder resolver estos problemas es necesario modificar las configuración de los navegadores y guardar estos cambios dentro de un perfil.

A continuación listaré y explicaré los pasos para crear estos perfiles con sus configuraciones necesarias para los drivers de Firefox y Chrome utilizando Python.

Firefox.

profile = webdriver.FirefoxProfile() #1

profile.set_preference("browser.download.folderList", 2)#2
profile.set_preference("browser.download.dir", cfg.temp_pdf)#3
profile.set_preference("browser.download.useDownloadDir", True)#4
profile.set_preference("browser.download.manager.showWhenStarting", False)#5
profile.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/pdf")#6
profile.set_preference("browser.download.manager.showAlertOnComplete", False)#7
profile.set_preference("browser.download.manager.useWindow", False)#7
profile.set_preference("pdfjs.disabled", True)#9
self.driver = webdriver.Firefox(profile)#10

Configuración para firefox.

  1. Se crea un perfil de firefox vacío.
  2. Con el número 2 le indicamos a firefox que debe utilizar la carpeta especificada en el paso 3.
  3. Acá le proporcionaremos a firefox la carpeta que queremos utilizar como directorio de descarga.
  4. Ahora activamos el uso del directorio asignado en el paso 3.
  5. Apagamos la animación de comienzo de descarga. (Opcional)
  6. Este paso es muy importante, acá le pasaremos como parámetro los MIME type que queremos descargar sin preguntarMás info sobre MIME types.
  7. Desactivamos animación de descarga completa. (Opcional)
  8. Deshabilitamos la ventana de descarga de firefox.
  9. Apagamos el plugin por defecto de firefox para leer archivos PDF.
  10. Instanciamos el driver de Firefox pasando como parámetro nuestro profile recién creado.

Chrome
chrome_profile = webdriver.ChromeOptions()#1
profile = {"download.default_directory": cfg.temp_pdf,
           "download.prompt_for_download": False,
           "download.directory_upgrade": True,
           "safebrowsing.enabled": True,
           "plugins.always_open_pdf_externally": True}#2
chrome_profile.add_experimental_option("prefs", profile)#3
chrome_profile.add_argument("--disable-extensions")#4
chrome_profile.add_argument("--disable-print-preview")#5
self.driver = webdriver.Chrome(chrome_options=chrome_profile)#6

Configuración para Chrome.

  1. Se crea un perfil de chrome vacío.
  2. Acá creamos un diccionario con las siguientes configuraciones.
    1. Directorio por defecto para las descargas de chrome.
    2. Acá apagamos  la ventana que pregunta donde ubicar y como llamar el archivo por descargar.
    3. Opción para que chrome pueda crear la ruta de descarga si es que no existe.
    4. Navegación segura activada. (Opcional)
    5. Para abrir el pdf externamente.
  3. Se añade el diccionario recién creado como las preferencias del perfil.
  4. Desactiva todas las extensiones de Chrome para evitar que algún plugin del navegador intente abrir los archivos PDF.
  5. Acá desactivamos la vista de impresión para evitar nuevamente que algo intente abrir los PDFs.
  6. Finalmente instanciamos el chromedriver pasando como parámetros el perfil de chrome recién creado.
Tal como pudimos apreciar, la configuración para evitar la interrupción de tests que contengan PDFs es un tanto compleja, ya que se debe tener en consideración muchas variables como lugar de descarga, desactivación de plugins, etc. Como comentario profesional siempre recomiendo descargar los pdfs utilizando código para no crear tests completamente dependientes de la máquina en que se están corriendo los tests, debido a que estos tipos de tests no van a funcionar al 100% en drivers provistos por saucelabs.

Como activar el comando python en el CMD de windows 10.

Un problema bastante común para los novatos de python que usan windows 10 es correr scripts en la linea de comando. Generalmente este proble...