Desarrollo guiado por comportamiento
En la Ingeniería de Software, behavior-driven development (BDD) o desarrollo guiado por el comportamiento (DGC) es un proceso de desarrollo de software que surgió a partir del desarrollo guiado por pruebas (DGP o TDD).[1][2][3] El desarrollo guiado por el comportamiento combina las técnicas generales y los principios del DGP, junto con ideas del diseño guiado por el dominio y el análisis y diseño orientado a objetos para proveer al desarrollo de software y a los equipos de administración de herramientas compartidas y un proceso compartido de colaboración en el desarrollo de software.[1][4]
Aunque el DGC es esencialmente una idea sobre cómo el desarrollo de software debería ser administrado tanto por los intereses del negocio como por el entendimiento técnico, la práctica del DGC asume el uso de herramientas de software especializadas para asistir en el proceso de desarrollo.[2] Aunque estas herramientas son comúnmente desarrolladas específicamente para su uso en proyectos de DGC, se pueden ver como formas especializadas de las herramientas que asisten en el DGP. Las herramientas sirven para agregar automatización para el lenguaje ubicuo (lenguaje estructurado alrededor del modelo de dominio, utilizado en el diseño guiado por el dominio para conectar actividades entre miembros del equipo), el cual es el tema central del DGC.
Historia
El desarrollo guiado por el comportamiento fue desarrollado por Dan North como respuesta a los problemas que surgían al enseñar el desarrollo guiado por pruebas:[1]
- Dónde comenzar en el proceso
- Qué probar y qué no probar
- Qué tanto abarca una prueba
- Cómo llamar a las pruebas
- Cómo entender por qué falla una prueba
En el corazón del DGC existe una reconsideración de la aproximación a la prueba unitaria y a la prueba de validación que North sugirió mientras lidiaba con estos problemas. Por ejemplo, él propone que los nombres de las pruebas unitarias sean oraciones completas empezando con la palabra "deber"/"debería" y que deberían estar escritas en el orden de importancia de rentabilidad en el negocio. Las pruebas de validación deberían estar escritas usando el armazón estándar ágil de una historia de usuario: "Como un [rol] yo deseo [características] para que así exista [beneficio]". Los criterios de validación deberían estar escritos en términos de las situaciones y además implementados como cláusulas: (usando el principio Given-When-Then) Dado que [contexto inicial], cuando [ocurre el evento], entonces [asegurar algunos resultados].[1]
A partir de este punto, North y otros desarrollaron el armazón del DGC en el transcurso de algunos años, finalmente enmarcándolo como un armazón de comunicación y colaboración para desarrolladores, para el aseguramiento de la calidad y para participantes no técnicos o enfocados en los negocios en un proyecto de software.[5][6] Durante el congreso "Especificaciones ágiles, DGC y Pruebas" ("Agile specifications, BDD and Testing eXchange") en noviembre de 2009 en Londres, Dan North[7] dio la siguiente descripción del DGC:
El DGC es una metodología ágil de segunda generación, tipo afuera hacia adentro, basada en jalar, siendo vehículo de múltiples partes interesadas, de escala múltiple, y de alta automatización. Describe un ciclo de interacciones con producciones bien definidas, resultando en el envío de software funcional, probado y trascendente.
Dan North creó el primer armazón del DGC, JBehave,[1] seguido por un armazón nivel de historia DGC para Ruby llamado RBehave,[8] el cual fue integrado más tarde al proyecto RSpec.[9] North también colaboró con David Chelimsky, Aslak Hellesøy entre otros, para desarrollar RSpec y también para escribir el libro "The RSpec Book: Behaviour Driven Development with RSpec, Cucumber, and Friends". El primer armazón basado en historia dentro de RSpec fue reemplazado poco tiempo después por Cucumber, principalmente desarrollado por Aslak Hellesøy.
En el 2008, Chris Matts, quien estuvo involucrado en las primeras discusiones alrededor del DGC, ideó el Feature Injection (inserción de característica), logrando así que el DGC pudiera cubrir el espacio de análisis y proveer un tratamiento completo al ciclo de vida del software, desde la visión hasta el código y el lanzamiento.
Principios del DGC
En sí, el desarrollo guiado por el comportamiento es una forma especializada de la lógica de Hoare aplicada al desarrollo guiado por pruebas, y que finalmente se enfoca en especificaciones conductistas acerca de las unidades de software que usan el lenguaje del dominio de la situación.
El desarrollo guiado por pruebas (TDD) es una metodología de desarrollo de software que esencialmente afirma que por cada unidad de software, un desarrollador de software debe:
- primero definir un conjunto de pruebas para la unidad;
- después implementar la unidad;
- finalmente verificar que la implementación de la unidad haga exitosas las pruebas.
Esta definición es poco específica, referente a que permite pruebas en términos de requerimientos de software de alto nivel, detalles técnicos de bajo nivel o cualquier cosa entre éstos límites. El desarrollador original del DGC (Dan North) propuso la noción del DGC debido a que no estaba satisfecho con la falta de especificaciones dentro del DGP, referente a lo que debe ser probado y cómo.[10] Una forma de ver al DGC entonces, es que es un desarrollo continuo del DGP, por lo que toma decisiones más específicas que el DGP.
El desarrollo guiado por el comportamiento señala que las pruebas de cualquier unidad de software deben ser especificadas en términos del comportamiento deseado de la unidad.[2][4][10] Tomando prestado del desarrollo ágil de software, el concepto de "comportamiento deseado" en este caso consiste en los requerimientos definidos por el negocio -- esto es, el comportamiento deseado que tiene valor rentable para cualquier entidad que haya comisionado la unidad de software que se encuentra en construcción.[2][10] Dentro de la práctica del DGC, esto es lo que apunta a que el DGC es una actividad "afuera-hacia-adentro".[11]
Especificaciones del comportamiento
Siguiendo esta decisión fundamental, una segunda decisión hecha por el DGC se relaciona con el cómo debe ser especificado el comportamiento deseado. En esta área el DGC escoge usar un formato no completamente formal para especificar el comportamiento. Esto se toma prestado de las especificaciones de la historia de usuario, específicamente del campo de análisis y diseño orientado a objetos. El DGC especifica que los analistas de negocios y los desarrolladores deben colaborar en esta área y además deben señalar el comportamiento en términos de las historias de usuario, las cuales son escritas explícitamente en un documento dedicado.[10][11] Cada historia de usuario, de alguna forma, debe seguir la siguiente estructura de seguimiento:[2][11]
- Título: La historia debe tener un título claro y explícito.
- Narrativa
- Una pequeña sección de introducción que especifique
- quién (cuál negocio o rol del proyecto) es el conductor o principal parte interesada de la historia (el actor que recibe beneficios de la historia)
- qué efecto se quiere en la historia, señalado por la parte interesada
- qué remuneración tendrá la parte interesada a partir de este efecto
- Criterios de aceptación o escenarios
- Es una descripción de cada caso específico de la narrativa. Tal escenario tiene la siguiente estructura:
- Comienza al especificar la condición inicial, la cual es asumida como verdadera al inicio del escenario. Esto puede consistir en una causa o varias.
- Después declara cuál evento causa el inicio del escenario.
- Finalmente, declara el resultado esperado, en una o más cláusulas.
El DGC no tiene requerimientos formales para describir exactamente cómo estas historias de usuario deben ser escritas, pero sí insiste en que cada equipo utilizando el DGC declare un formato simple y estandarizado para escribir las historias de usuario, el cual incluye los elementos listados arriba.[2][11] Sin embargo, en 2007 Dan North sugirió una plantilla para un formato textual, la cual ha encontrado amplio seguimiento en diferentes herramientas DGC de software.[11] Un pequeño ejemplo de este formato puede verse así:
Historia: Devoluciones van al inventario A fin de tener seguimiento del inventario Siendo un dueño de tienda Yo quiero añadir artículos de regreso al inventario cuando sean devueltos Escenario 1: Artículos reembolsados deben ser regresados al inventario Dado que un cliente previamente me compró un suéter negro Y actualmente me quedan tres suéteres negros en el inventario Cuando él devuelva el suéter a cambio de un reembolso Entonces yo debo tener cuatro suéteres en el inventario Escenario 2: Artículos reemplazados deben ser regresados al inventario Dado que un cliente compra una prenda azul Y yo tengo dos prendas azules en el inventario Y tres prendas negras en el inventario Cuando él regresa la prenda para un reemplazo por una negra, Entonces yo debo tener tres prendas azules en el inventario Y dos negras en el inventario
Los escenarios están idealmente expresados de una forma declarativa en lugar de imperativa -- en el lenguaje del negocio, sin referencia a los elementos de la UI, a través de la cual las interacciones ocurren.[12]
Este formato es conocido como el lenguaje Gherkin, que tiene una sintaxis similar al ejemplo de arriba. El término Gherkin, sin embargo, es único para las herramientas de software Cucumber, JBehave y Behat.[13][14][15]
La especificación como lenguaje ubicuo
El desarrollo guiado por el comportamiento toma prestado el concepto de lenguaje ubicuo del diseño guiado por el dominio.[2][4] Un lenguaje ubicuo es un lenguaje semiformal compartido por todos los miembros de un equipo de desarrollo de software -- tanto desarrolladores de software como personal no técnico.[16] El lenguaje en cuestión es usado y desarrollado por todos los miembros del equipo para ser un medio común para la discusión del dominio del software en cuestión.[16] De esta forma el DGC se convierte en un vehículo para la comunicación entre todos los roles diferentes en un proyecto de software.[2][6]
Un riesgo común con el desarrollo de software incluye fallos en la comunicación entre desarrolladores y partes interesadas en el negocio (inversores).[17] El DGC usa la especificación del comportamiento deseado como un lenguaje ubicuo para los miembros del equipo del proyecto. Esta es la razón de que el DGC insiste en usar un lenguaje semiformal para la especificación del comportamiento: sólo un poco de formalidad es un requerimiento para ser un lenguaje ubicuo.[2] Asimismo, tener tal lenguaje crea un modelo de dominio de especificaciones, para que así las especificaciones puedan ser reflexionadas formalmente.[18] Este modelo es también base para las diferentes herramientas de software disponibles que usan DGC.
El ejemplo dado arriba establece una historia de usuario para un sistema de software en desarrollo. Esta historia identifica a la parte interesada, un efecto de negocio y valor de negocio. Asimismo describe varios escenarios, cada uno con una precondición, un detonador y un resultado esperado. Cada una de estas partes está definida exactamente por la parte más formal del lenguaje (el término Dado que puede considerarse como una palabra clave, por ejemplo) y por tal causa es posible que sea procesada de alguna manera por una herramienta que entienda las partes formales del lenguaje ubicuo.
Utillaje de asistencia especializada
Muy parecido a lo que es la práctica del diseño guiado por pruebas, el DGC asume el uso de utillaje de asistencia especializada en un proyecto. Por más que el DGC sea, en muchos aspectos, una versión más específica del DGP, el utillaje para DGC es similar al de DGP, pero le hace más demandas al desarrollador que el utillaje básico de DGP.[cita requerida]
Principios de utillaje
En principio una herramienta de soporte DGC es un armazón para probar software, similar a las herramientas que asisten al DGP. Sin embargo, donde las herramientas DGP tienden a ser libres de formato referente a lo que se permite para pruebas de especificación, las herramientas DGC están relacionadas con la definición del lenguaje ubicuo discutida anteriormente.
Como se mencionó, el lenguaje ubicuo permite a los analistas de negocios el escribir requerimientos de comportamiento de tal forma que los desarrolladores lo puedan entender. El principio del utillaje de asistencia DGC es el convertir estos documentos de requerimientos directamente ejecutables en una colección de pruebas. La implementación exacta de esto varía por cada herramienta, pero la práctica ágil ha presentado el proceso general siguiente:
- El utillaje lee un documento en específico.
- El utillaje entiende directamente las partes completamente formales del lenguaje ubicuo (como la palabra clave Dado que). Basado en esto, la herramienta divide cada escenario en cláusulas relevantes.
- Cada cláusula individual en un escenario se transforma en un tipo de parámetro para la prueba de la historia de usuario. Esta parte requiere trabajo específico del proyecto por parte de los desarrolladores..
- El armazón después ejecuta la prueba para cada escenario, usando los parámetros que le pertenecen a ese escenario.
Dan North ha desarrollado un número de armazones que apoyan el uso del DGC (incluyendo JBehave y RBehave), cuya operación se basa en la plantilla que él sugirió para recopilar historias de usuarios.[2] Estas herramientas usan una descripción textual para casos de uso y varias otras herramientas (como CBehave). Sin embargo, este formato no es requerido y por lo tanto hay otras herramientas que usan otros formatos también. Por ejemplo Fitnesse (que se construyó alrededor de tablas de decisión), también se ha usado para desplegar DGC.[19]
Ejemplos del utillaje
Existen varios ejemplos diferentes del utillaje de software de DGC para uso en proyectos hoy en día, para distintas plataformas y lenguajes de programación.
Posiblemente el más conocido es JBehave, que fue desarrollado por Dan North. El siguiente es un ejemplo tomado de ese proyecto:[14]
Considere una implementación del Juego de la vida. Un experto en dominios (o analista de negocios) tal vez quiera especificar lo que deba pasar cuando alguien prepara una configuración de inicio en la red del juego. Para lograr esto, él tal vez quiera dar un ejemplo del número de pasos dados por una persona que está cambiando de celdas. Saltándonos la parte narrativa, él tal vez haga esto al escribir el siguiente escenario en un documento de texto común y corriente (que es el tipo de documento de ingreso que JBehave lee):
Dado que se tiene un juego 5 por 5 Cuando yo alterne la celda en (3, 2) Entonces la red debería verse así ..... ..... ..... ..X.. ..... Cuando yo alterne la celda en (3, 1) Entonces la red debería verse así ..... ..... ..... ..X.. ..X.. Cuando yo alterne la celda en (3, 2) Entonces la red debería quedar así ..... ..... ..... ..... ..X..
Las palabras resaltadas no son parte de la entrada; se incluye aquí para mostrar cuáles palabras se distinguen como lenguaje formal. JBehave reconoce los términos Dado que (como precondición que define el inicio de un escenario). Cuando (como un detonador) y Entonces (como una pos-condición que debe ser verificada como el resultado de la acción que le sigue al detonador). Basado en esto, JBehave es capaz de leer el archivo de texto que contiene el escenario y de hacer un análisis sintáctico para convertirlo en cláusulas (una cláusula de preparación y después tres detonadores de eventos con condiciones verificables). JBehave después toma estas cláusulas y las pasa a código que es capaz de preparar una prueba, respondiendo a los detonadores de eventos y verificando el resultado. Este código debe estar escrito por los desarrolladores en el equipo del proyecto (en Java, porque esa es la plataforma en que se basa JBehave). En este caso, el código puede verse así:
private Game game;
private StringRenderer renderer;
@Given("a $width by $height game")
public void theGameIsRunning(int width, int height) {
game = new Game(width, height);
renderer = new StringRenderer();
game.setObserver(renderer);
}
@When("I toggle the cell at ($column, $row)")
public void iToggleTheCellAt(int column, int row) {
game.toggleCellAt(column, row);
}
@Then("the grid should look like $grid")
public void theGridShouldLookLike(String grid) {
assertThat(renderer.asString(), equalTo(grid));
}
El código tiene un método para cada tipo de cláusula en un escenario. JBehave identificará cuál método va con cuál cláusula a través del uso de anotaciones y podrá llamar a cada método en orden mientras corre el escenario. El texto en cada cláusula en el escenario tiene que ser el mismo al de la plantilla de texto dada en el código para esa cláusula (por ejemplo, a Dado que en un escenario debe seguir una cláusula de la forma "juego X por Y"). JBehave espera la coincidencia de cláusulas con plantillas y tiene integrado el apoyo para escoger términos de la plantilla y pasarlos a los métodos en el código de prueba como parámetros. El código de prueba provee la implementación para cada tipo de cláusula en un escenario, la cual interactúa con el código que está siendo probado y lleva a cabo una prueba basada en el escenario. En este caso:
- El método "juego está corriendo"
theGameIsRunning
reacciona a la cláusula Dado que al preparar el juego de red inicial. - El método "alterno la celda en"
iToggleTheCellAt
reacciona a la cláusula Cuando al disparar el evento de alternar que está descrito en la cláusula. - El método "la red debería verse así"
theGridShouldLookLike
reacciona a la cláusula Entonces al comparar el estado actual de la red del juego al estado esperado del escenario.
La función primaria de este código es el ser un puente entre un archivo de texto con una historia y el código en sí que se está probando. Cabe recalcar que el código de prueba tiene acceso al código que está siendo probado (en este caso una instancia del Juego) y es muy simple en su naturaleza. El código de prueba tiene que ser simple, ya que de otra forma un desarrollador terminaría escribiendo pruebas para sus pruebas.
Finalmente, para logar correr las pruebas, JBehave requiere de un poco de "código de plomería" que identificará los archivos de texto que contienen escenarios y que agregan dependencias (como instancias de Juego) dentro del código de prueba. Este código de plomería no está ilustrado aquí, ya que es un requerimiento técnico de JBehave y no se relaciona directamente al estilo principal del estilo de prueba DGC.
Historia contra especificación
Una subcategoría separada del desarrollo guiado por el comportamiento es formada por herramientas que usan especificaciones como un lenguaje de entrada en lugar de usar historias. Un ejemplo de este estilo es la herramienta RSpec, que también fue desarrollada por Dan North. Las herramientas de especificación no utilizan historias de usuario como un formato de entrada para probar escenarios, sino que usan especificaciones funcionales para unidades que están siendo probadas. Estas especificaciones frecuentemente tienen una naturaleza más técnica que las historias de usuario y además son usualmente menos convenientes para la comunicación entre personal de negocios que las historias de usuario.[2][20] Un ejemplo de una especificación para una pila podría verse así:
Especificación: Pila Cuando una nueva pila sea creada Entonces está vacía Cuando un elemento es añadido a la pila Entonces ese elemento está en la cima de la pila Cuando una pila tiene N elementos Y el elemento E está en la cima de la pila Entonces una operación pop regresa a E Y el nuevo tamaño de la pila es N-1
Tal especificación puede especificar exactamente el comportamiento que se está probando, pero tiene mayor insignificancia para un usuario de negocios (inversionistas por ejemplo). Como resultado, las pruebas guiadas por la especificación aparecen en la práctica del DGC como un complemento a las pruebas guiadas por historias y operan a un menor nivel. Las pruebas de especificación son a veces vistas como un reemplazo para las pruebas unitarias con formato libre.[20]
Las herramientas de pruebas de especificación como RSpec y JDave son un tanto diferentes en naturaleza a otras como JBehave. Debido a que son vistas como alternativas a las herramientas básicas de pruebas unitarias como JUnit, estas herramientas tienden a favorecer el abstenerse a la separación de la historia y el probar código, en su lugar prefieren incrustar la especificación directamente en el código de prueba. Por ejemplo, una prueba RSpec para una tabla hash podría verse así:[21]
describe Hash do
let(:hash) { Hash[:hello, 'world'] }
it { expect(Hash.new).to eq({}) }
it "hashes the correct information in a key" do
expect(hash[:hello]).to eq('world')
end
it 'includes key' do
hash.keys.include?(:hello).should be true
end
end
Este ejemplo muestra una especificación en un lenguaje legible incrustado en código ejecutable. En este caso se escoge una herramienta para formalizar el lenguaje de especificación y meterlo en el lenguaje de código de prueba al agregar los métodos llamados (eso) it
y (debería) should
. Asimismo existe un concepto de una precondición para la especificación -- la sección (antes) before
establece las precondiciones en las que se basa la especificación.
Los resultados de la prueba serán:
Hash should eq {} includes key hashes the correct information in a key
Véase también
Referencias
- «Behaviour-Driven Development». Archivado desde el original el 1 de septiembre de 2015. Consultado el 12 de agosto de 2012.
- Haring, Ronald (febrero de 2011). «Behavior Driven development: Beter dan Test Driven Development». En de Ruiter, Robert, ed. Java Magazine (en neerlandés) (Veen Magazines) (1): 14-17. ISSN 1571-6236.
- Solis, Carlos; Wang, Xiaofeng. «A Study of the Characteristics of Behaviour Driven Development». Software Engineering and Advanced Applications (SEAA), 2011 37th EUROMICRO Conference on: 383 - 387. doi:10.1109/SEAA.2011.76.
- Bellware, Scott (junio de 2008). «Behavior-Driven Development». Code Magazine. Archivado desde el original el 12 de julio de 2012. Consultado el 12 de agosto de 2012.
- D.North, comments, The RSpec Book – Question about Chapter 11: Writing software that matters Archivado el 7 de noviembre de 2009 en Wayback Machine.
- North, Dan (31 de mayo de 2012). «BDD is like TDD if…». faster organisations, faster software. Dan North & Associates. Consultado el 12 de agosto de 2012.
- Dan North: How to sell BDD to the business Archivado el 25 de noviembre de 2010 en Wayback Machine.
- D.North, Introducing RBehave Archivado el 20 de junio de 2007 en Wayback Machine.
- S.Miller, InfoQ: RSpec incorporates RBehave
- North, Dan (marzo de 2006). «Introducing BDD». Dan North. Consultado el 12 de agosto de 2012.
- North, Dan (11 de febrero de 2007). «What’s in a Story?». Dan North. Consultado el 12 de agosto de 2012.
- Mabey, Ben. «Imperative vs. Declarative Scenarios in user stories». Archivado desde el original el 3 de junio de 2010. Consultado el 19 de mayo de 2008.
- «Gherkin». Consultado el 12 de agosto de 2012.
- «Gherkin». Consultado el 15 de mayo de 2013.
- «Gherkin». Archivado desde el original el 19 de septiembre de 2015. Consultado el 6 de enero de 2015.
- Evans, Eric (2003). Domain-Driven Design: Tackling Complexity in the Heart of Software. Addison-Wesley. ISBN 0-321-12521-5. Consultado el 12 de agosto de 2012.
- Geneca (16 de marzo de 2011). «Why Software Projects Fail». Consultado el 16 de marzo de 2011.
- Mahmudul Haque Azad (6 de febrero de 2011). «Say Hello To Behavior Driven Development». Consultado el 12 de agosto de 2012.
- Ketil Jensen (13 de diciembre de 2009). «BDD with Scenario tables in Fitnesse Slim». Walk the walk. Wordpress. Consultado el 12 de agosto de 2012.
- Roy Osherove (4 de octubre de 2008). «BDD: Behavior vs. Spec Frameworks». Consultado el 12 de agosto de 2012.
- Jason Seifer (7 de diciembre de 2011). «An Introduction To RSpec». Consultado el 27 de octubre de 2012.
Enlaces externos
- Dan North's article introducing BDD
- Say Hello To Behavior Driven Development (BDD)- Part 1
- Say Hello To Behavior Driven Development (BDD)- Part 2
- Behavior Driven Development Using Ruby (Part 1)
- Behavior-Driven Development Using Ruby (Part 2)
- In pursuit of code quality: Adventures in behavior-driven development by Andrew Glover
- The RSpec Book: Behaviour Driven Development with RSpec, Cucumber, and Friends
- ScalaTest: Tests as specifications
- Unit test JavaScript applications with Jasmine (including behavior-driven development)
- Chai BDD/TDD Javascript Library Assertion Styles
- Choosing a BDD framework for .NET
- Using Keywords to Support Behavior Driven Development by Hans Buwalda