miércoles, 10 de octubre de 2018

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 problema aparece cuando se quiere instalar pip (este modulo se instala corriendo un script).











Para poder arreglar este problema se necesita agregar Python como una variable de entorno para que de esta forma CMD lo reconozca como un comando válido.

Pasos a seguir.

1) Abre el explorador de windows y haz click derecho sobre 'Este Equipo'.























2) Ahora haz click sobre el vínculo 'Configuración avanzada del sistema' para obtener la ventana de Propiedades del sistema.






















3) En esta ventada debes hacer click en el botón Variables de entorno...






















4) En la nueva ventana haz doble click sobre la fila de la variable Path. Nota: Puedes hacerlo para el usuario o para el sistema completo. Recomiendo hacerlo para el sistema.)





















5) Presionamos Nuevo en esta ventana y pegamos la ubicación de la carpeta de python. En mi caso la ésta se encuentra en C:/Python27.





















6) Apretamos aceptar y luego aceptar en la ventana de Propiedades del sistema.

Con esto debería estar todo listo.

Para verificar abre el CMD (si estaba abierto durante este proceso ciérra y vuelve a abrirlo.) y tipea python.












¡Como ves todo funciona de maravilla!



viernes, 25 de mayo de 2018

Page Object

 ¿Qué es un Page Object?

Page Object es un patrón de diseño con el cual buscamos crear un objeto que sirva como una capa de abstracción para las interacciones que se pueden efectuar en una página web. Es decir, un page object debe proveer una manera simple para interactuar con una página web encapsulando sus funcionalidades y características.



¿Por qué usar page objects?

Los page objects nos entregan una manera sencilla de interactuar con las páginas web que queremos verificar en nuestros tests. Esto le quita mucha complejidad a nuestros tests, ya que nosotros para realizar acciones u obtener datos de la página web, solamente debemos llamar los métodos del objeto. Esto reducirá dramáticamente la cantidad de código en nuestros tests. Disminuyendo sus complejidad, mantenimiento y facilitando el patrón AAA (Arrange, Act y Assert.).

Consejos para el manejo de elementos.

Campo de texto (Input text y text areas).

Usualmente los campos de texto son elementos html que aceptan texto libre en su interior.

Extracción de datos.

Se debe tener un método para extraer el contenido de dicho campo y retornarlo como un String.

Asignación de datos.

Se debe tener un método para poder ingresar datos a ese campo. Lo ideal es que este método reciba un String como parámetro

Radio buttons.

Los radio buttons son un conjunto de elementos que comparten el atributo name y se diferencian entre ellos por el valor que ellos contienen.

Extracción de datos.

Se debe tener un método que retorne el valor del botón seleccionado de la familia.

Asignación de datos.

Se debe tener un método que debería ser capaz de seleccionar el elemento de la familia mediante un parámetro de texto que concuerde con uno de los elementos de la familia.

Checkboxes.

Los checkboxes son elementos que pueden ser clickeados para  cambiar su estado a 'checked'.

Extracción de datos.

Se debe tener un método que retorne True o False.

Asignación de datos.

Se debe terner un método que asigne mediante un parámetro booleano para cambiar la selección de dicho objecto. True para que pase a estar 'checked' y False para remover remover el atributo 'checked'.

Listas desplegables (Selects).

Las listas deplegables son elementos que contienen opciones para ser seleccionadas por el usuario. Las opciones tienen dos principales características, una es el texto visible y la otra es el valor de la opción. Dichas características no siempre comparten valor.

Extracción de datos.

Se debe tener métodos que retornen el valor, texto o índice de la opción seleccionado en la lista desplegable.

Asignación de datos.

Se debe tener métodos para poder seleccionar la opción por valor, texto o indice.

Conclusión.

El page object es un patrón de diseño que nos ayudarás a disminuir la complejidad de nuestros tests. Debido a que nos entregará menos código por mantener, mayor abstracción en nuestras pruebas y una complejidad menor en nuestros tests.

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 preguntar. Má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.

jueves, 27 de octubre de 2016

Introducción a Vagrant

¿Qué es Vagrant?
Vagrant es una herramienta opensource la cual permite la creación de entornos virtuales donde los desarrolladores pueden trabajar libremente independiente del sistema operativo que ellos estén utilizando.

¿Por qué usar Vagrant?
Vagrant es extremadamente simple de utilizar, por lo tanto, sus archivos de configuración son fáciles de reproducir y portables. Además posee una cantidad gigantesca de boxes para llegar e instalar, por ejemplo: hay boxes de diferentes versiones de ubuntu e incluso otras con todo lo necesario para comenzar a utilizar laravel o un servidor lamp. A estas alturas, Vagrant es un estándar de la industria del software.

Prerrequisitos para utilizar vagrant.
Para poder utilizar vagrant necesitamos un virtualizador de máquinas virtuales, siempre se recomienda utilizar Virtualbox. La razón de esto, es que el proyecto Vagrant ha sido ideado para trabajar con esta aplicación.

Instalación de Vagrant.
Despues de instalar Virtualbox es necesario ir a la página de descargas de Vagrant y descargar el instalador para tu sistema operativo. Al tener el instalador, en nuestra máquina debemos ejecutarlo e instalar Vagrant. En Mac y Windows esto es muy fácil, por lo tanto, solamente enseñaré como instalarlo en sistemas GNU/Linux.
  1. Abre un terminal.
  2. Ve al directorio donde está el instalador de Vagrant.
  3. Ejecuta el siguiente comando.
    $ sudo dpkg -i vagrant_TU_ARCHIVO.deb
  4. Para verificar la instalación, ejecuta este comando para ver la versión de Vagrant.
    $ vagrant -v

Creando y corriendo nuestra primera máquina Vagrant.
¡Ahora que tenemos todo lo necesario instalado podremos crear nuestra primera máquina Vagrant!. Para poder hacer esto, ejecuta los siguiente pasos:
  1. Abre un terminal y crea un directorio de prueba.
  2. Ve al directorio recién creado y ejecuta los siguientes comandos.
    $ vagrant init hashicorp/presice64
    $ vagrant up
¿Qué hicimos con estos comandos?
Con 'vagrant init hashicorp/precise64' le ordenamos a vagrant que cree un archivo Vagrantfile con todo lo necesario para descargar la box hashicorp/precise64. Después con el comando 'vagrant up', Vagrant utiliza el Vagrantfile para descargar la box solicitada y después levantar la máquina virtual cuando todo esté listo.

Accediendo a la máquina Vagrant.
Para acceder ala máquina recién creada debes ejecutar el siguiente comando:
$ vagrant ssh
Después de esto nos encontraremos dentro de la máquina virtual y podremos ejecutar todos los comandos que queramos. Cabe mencionar que vagrant siempre crea credenciales root en la máquinas virtuales que son levantadas con sus boxes públicas, usualmente estás credenciales  son:
Usuario: vagrant
Password: vagrant

Conclusión.
Cómo se comentó al comienzo de este post, Vagrant es una excelente solución para levantar entornos de desarrollo replicables y fáciles de configurar. Siguiendo los pasos descritos podemos demostrar la facilidad de uso de esta tecnología.

Cabe mencionar, que esta es la primera entrada de varios tutoriales y tips que compartiré de Vagrant, por lo tanto, no te enojes con la simpleza de este post jeje.

sábado, 15 de octubre de 2016

Downgrade de Firefox para no perder la compatibilidad con webdriver.


Uno de los últimos grandes problemas que me he enfrentado como QA de automatización ha sido el problema de compatibilidad de webdriver con Firefox. A partir de la versión 47 de Firefox,  no será posible utilizar webdriver con este navegador. Es decir, ya no podremos simplemente llamar a webdriver.Firefox() para hacer uso de él.

Las solución actual ante esto es instalar marionette. Suena fácil, pero créanme que no lo es. Es necesario hacer diferentes tipos de instalaciones por sistema operativo, lo cual no es lo ideal si estamos trabajando en testing multiplataforma.

Como notaran por mis palabras, no fui capaz de instalar marionette en el framework de automatización en el que trabajo. Me niego rotundamente a hacer una instalación ad hoc para cada sistema operativo, esto rompe totalmente la filosofía de mi trabajo. Por lo tanto, decidí hacer un downgrade de Firefox y esperar por una mejor solución al instalar marionette.

En sistemas operativos como OSX o Windows se puede desactivar las actualizaciones fácilmente mediante las opciones de configuración de Firefox. Por lo tanto, ahora compartiré la solución que utilicé para Ubuntu. Dicha solución es la siguiente:

1. Abrir un terminal.

2. Después debes correr este comando para instalar la versión 45 de Firefox:
sudo apt-get install firefox=45.0.2+build1-0ubuntu1
Nota: Puede que el sistema te advierta de que se llevará a cabo un downgrade, da tu consentimiento para continuar. 3. Para mantener la versión de Firefox sin permitir updates, se debe usar este comando:
sudo apt-mark hold firefox
Nota: Esto excluirá Firefox de cualquier actualización. Si quieres remover este cambio, es decir, volver a aceptar actualizaciones en Firefox, utiliza estos comandos para revertir el estado actual.
sudo apt-mark unhold firefox
sudo apt-get upgrade
Conclusión. Con estos cambios Firefox no volverá a ser actualizado, por lo cual podremos continuar usando sin problemas webdriver con Firefox, mientras esperamos por una versión más madura de marionette.

miércoles, 28 de septiembre de 2016

El costo de los bugs

El software no es un producto que aparece por arte de magia. Generalmente es planeado y pasa por varias etapas antes de ser lanzado. Por lo tanto, pasando por su planificación, desarrollo, testeo y lanzamiento, existe la posibilidad de encontrar bugs en cualquiera de estas etapas. En la siguiente figura se grafica qué tan caro es arreglar un bug dependiendo de la etapa de desarrollo en donde es encontrado.

El costo de arreglar un bug tiende a aumentar de manera exponencial como se puede apreciar en la figura. Dicho esto, si encontramos un bug en la etapa de diseño el costo de arreglarlo será bajo. ¿Pero que pasa si ese problema aparece en la etapa de testeo? dependiendo del proceso de desarrollo que se está utilizando esto puede variar. Trabajando con scrum, la tarea con problemas puede ser devuelta fácilmente a desarrollo, pero ésta de todas formas consume tiempo, pero no es lo mismo en el caso de un proceso de desarrollo más lento en donde los cambios se pasan a un servidor de prueba una vez al día.

Otro caso para analizar es cuando el cliente se encuentra cara a cara con un bug, como muestra la figura, el costo es 100 veces mayor a que si este hubiese sido encontrado en diseño. ¿Por qué será tan caro? La respuesta es simple, un bug encontrado por el cliente debe ser arreglado de manera inmediata en la mayoría de los casos, por lo tanto, la característica recién lanzada será retornada al proceso de desarrollo, en consecuencia a esto, la carga de trabajo aumentará considerablemente para el equipo. Además en algunos casos será necesario enviar el arreglo a producción antes de la fecha en que regularmente se hace, lo cual agrava más este escenario, ya que se debe aplicar todo el esfuerzo de un lanzamiento en una fecha no prevista.

Como pudimos apreciar, encontrar errores en etapas avanzadas del proyecto pueden ser perjudiciales para el equipo en términos de tiempo, esfuerzo e incluso dinero. Para evitar estos problemas es necesario utilizar estrategias preventivas como tests de regresión o unit testing en el lado de los desarrolladores. En síntesis, es esencial esforzarse desde el comienzo del proyecto en la búsqueda o prevención de bugs, para así poder capturar la mayor cantidad de errores en las etapas de diseño y desarrollo. 

martes, 27 de septiembre de 2016

Definición de un bug.


Llamar bugs a todos los problemas encontrados en un software puede ser la manera más simple de hacerlo, pero en definitiva no es una definición completa. Para entregar la definición correcta es necesario comprender qué es un problema y cómo estos se presentan dentro del software.

El primer término que nos ayudará con esto es especificación de producto: Una especificación de producto, comúnmente mencionado como especificación o spec, es un acuerdo entre todo equipo de desarrollo de software. Esto define el producto que se está creando, detalla qué debe ser, cómo debe actuar, qué debe y que no debe hacer. Este acuerdo puede ir desde un entendimiento verbal hasta un documento formal.

Ahora que hemos definido que es un spec, detallaremos las cinco principales reglas que ocurren cuando un bug aparece:
  1. El software no hace algo que la especificación del producto dice que debe hacer.
  2. El software hace algo que el la especificación del producto dice que no debe hacer.
  3. El software hace algo que el la especificación del producto no menciona.
  4. El software no hace algo que que la especificación del producto no menciona, pero debería.
  5. El software es difícil de entender o usar, lento o simplemente incorrecto.
Para comprender mejor estas reglas, las pondremos en práctica testeando las funcionalidades de una supuesta calculadora que se está desarrollando.

El spec principal de nuestra calculadora es que en ella se pueda sumar, restar, dividir y multiplicar sin ningún problema. Si al momento de testear la calculadora descubrimos que estos cálculos no se están haciendo correctamente, por ejemplo: restas con resultados negativos congelan la aplicación. En este caso estaremos enfrente de un bug causado por la primera regla.

Otro spec del producto dice que la calculadora nunca se debe congelar, crashear o bloquear. Si al momento de apretar teclas de manera aleatoria, creando cálculos aritméticos sin sentido, la calculadora se bloquea. Estamos ante un bug causado por la segunda regla.

Como indicamos en el primer problema, la calculadora debe poder sumar, restar dividir y multiplicar. Supongamos que el desarrollador agregó la funcionalidad para obtener la raíz cuadrada de un número  porque pensó que sería una característica genial. El problema es que esto nunca fue especificado, por lo tanto, esta nueva característica se convierte en un bug siguiendo la tercera regla.

El caso de la cuarta regla es un poco especial, debido a que estamos ante un enunciado que posee doble negativo. Supongamos que nuestra calculadora funciona correctamente cuando se hacen divisiones que tienen resultados con pocos decimales. pero al momento de testear exhaustivamente las divisiones nos damos que cuando el resultado tiene más de 10 dígitos en su decimal la fuente de la calculadora se torna pequeña e ilegible. En este caso estamos ante un problema de usabilidad que obviamente nunca se mencionó en la especificación del producto. Dicho bug es causado por la cuarta regla.

En el caso de que nuestra calculadora sea difícil de utilizar, posea teclas muy pequeñas, su texto sea ilegible, su configuración sea muy compleja, etc. En síntesis, cualquier problema que no luzca correcto, afecte su usabilidad o arruine la experiencia del usuario final será bug causado por la quinta regla.

Como pudimos ver con los ejemplos mencionados, los bugs pueden aparecer de diferentes formas en un software, por lo tanto un bug es una falla, algo no especificado, inconsistencias o problemas que afectan la experiencia del usuario al utilizar el software.

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...