Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

TDD

No description
by

Fabian Dario

on 14 May 2014

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of TDD

it('should get an error message', function () {
var fileTest = { filename:'', content: '{}' },
messageError = '';

scope.$on(events.propertyController.getFile, function (e, filename, done) {
done(fileTest);
});
scope.$on(events.error, function (e, message) {
messageError = message;
});

scope.reset();
expect(messageError).toBe(_.string.sprintf(scope.resources.READ_PROPERTY_FILENAME, ''));
});
test\unit\propertyModule\propertyControllerSpec.js
Que es TDD?
Ejemplo
Buenas Prácticas
Test Patterns
Proceso de desarrollo
Herramientas
Test-Driven JavaScript
Development

Generales
Proceso de desarrollo de software que combina el escribir las pruebas antes del correspondiente código y luego hacer
refactoring
.

Reduce el tiempo de diseño
Pensar en componentes
Crear al 100% una suite de pruebas de regresión
Las pruebas unitarias son suficientes
Las pruebas unitarias definen completamente la especificación de diseño
Focos en la calidad
Tendencia
Reduce el tiempo dedicado a depurar
Cambio de cultura
Puede restringir el estilo de codificación
Progreso lento
Toma tiempo entrenar al equipo
Retroalimentación rápida
Aumenta la calidad
Flexibilidad en el desarrollo
Código solido y simple
Aumenta la confianza del equipo
Test como un activo
Incrementa la productividad
Versiones de producción con un bajo porcentaje de defectos
Legibilidad de la aplicación
Diseño
Pruebas e integración
Código
Diseño
Pruebas
Código
Integración
Fail
Escribimos un caso de prueba.
Pass
Hacer pasar el test.
Refactor
Una vez esta la funcionalidad se mejora el diseño de la solución, elimina la duplicación, etc
Proceso de desarrollo con TDD
Iterativo
Ejecutar el test y verificar que la prueba falla.
El desarrollador implementa la funcionalidad escribiendo el código simple.
Ejecutar el test y verificar que pase.
Escribir el test
Verificar que el test falle
Escribir el código
El test se ejecutó correctamente
el test falló
Ejecutar la prueba
Refactor
Test falla
Los test se ejecutan
correctamente
Pasos
Automatización
Karma : Test runner
Grunt : Task runner
Node.js

Node Packaged Modules
Test Framework
Mocha
ng-scenario
Calidad del Código
Suite de pruebas
Casos de pruebas
Aserciones
Pruebas de operaciones asíncronas
Dependencias
Detectar errores sintácticos y malas prácticas, ayuda a prevenir bugs y comportamiento inesperado.
No duplicar aserciones.
Evitar escribir malas pruebas.
Hacer código testeable.
Pruebas cortas para no perder el foco.
Cada prueba debe centrarse en un solo comportamiento del modulo/función.
Evitar lógica de bifurcación.
Escribir código limpio.
Ejecutar las pruebas.
Ambiente de automatización rápido.
Legibilidad
Prueba debe ser fácil de leer.
Nombres claros
El nombre debe revelar la intensión del test.
El nombre es lo primero que se pone.
Escaneabilidad
Dar un bueno nombre, usar cadenas de texto q sean legibles, no es necesario usar _ o camelcase.
Usar la palabra "should" para describir el comportamiento.
Nombres cortos sin sacrificar la claridad.
Evitar prefijos, ej: Test
Evitar el uso de AND en un mismo caso, eso quiere decir q se esta probando mas de una cosa en el mismo caso.
Caso de prueba
Configurar
Verificar
Ejecutar
Alto nivel de abstracción
Mantener las pruebas cortas y simples.
Evitar el comportamiento complejo de un caso de prueba.
Dominio especifico para los casos de pruebas : no dejar funciones helper para pruebas en el código de producción.
Reducir la duplicación, no la claridad
Se pueden eliminar test duplicados verificando que que no se altere el comportamiento de la prueba.
Prueba como la especificación de un comportamiento
Escribir solo el código necesario.
Una prueba unitaria debería centrarse en un comportamiento especifico del sistema.
En una prueba pueden existir más de una aserción pero solo si están prueban ese único comportamiento.
Volver a probar comportamientos que ya examinaron en pruebas existentes no agrega valor a la especificación del sistema, agrega carga al mantenimiento.
Lucha contra los bugs
Ejecutar las pruebas antes de pasarlas.
El test asegura que el código será testeable.
Código de ruptura
La suite esta verde, pero en producción el código muestra defecto.
Las partes solas funcionan bien pero al integrarlas genera bugs.
Introducir intencionalmente bugs en el código y comprobar que los test fallen.
Introducir errores en cada loop uno por uno.
Test Doubles
Stunt
Fake Object
Dummy Object
Test Verification
State
Behavior
Stubs
Mocks
Spies
Se inyectan en el sistema de forma individual a medida que sean requeridos
Proporciona la misma funcionalidad del objeto q sustituye, puede ser visto como una implementación alternativa, pero su aplicación es considerablemente mas simple. Ej: manejo de archivos. El objeto real puede hacer mas lentas las pruebas o no tener acceso a todos los recursos q necesita. Los fake son mas completos y se inyectan antes de iniciar cualquier prueba
Objeto vacío o función. Es usado cuando una función lanza un error porque espera un argumento especifico, se puede pasar un dummy para centrar la prueba en el comportamiento de la función y no en los argumentos relacionados.
Tienen un comportamiento programado, retornan un valor especifico independiente de los argumentos.
Los objetos que imitan el comportamiento de objetos reales de una forma controlada.
Primero se declaran las expectativas, se realizan las operaciones en el sistema y finalmente se verifica.
Son objetos o funciones que registran información sobre como son usados a lo largo de un sistema bajo pruebas.
Ventajas
Desventajas
Proceso de desarrollo tradicional
Proceso de desarrollo con TDD
Centrarse en el que y en el por qué y no en el como.
Un refactor puede obligar a cambiar las pruebas. Ej: al cambiar un constructor.
1. Mostrar una lista de tareas

2. Crear una tarea.

3. Marcar una tarea como completada.

4. Crear una tarea con prioridad.

5. Filtrar las tareas por prioridad.

Historia de Usuario
Como un usuario debería poder ver el listado de tareas
Escenario
: Mostrar el listado de tareas
Cuando
navegue al listado de tareas,
debería
ver el listado de tareas

Historia de Usuario
Como usuario debería poder agregar una nueva tarea y verla en el listado.

Escenario
: Agregar una tarea valida
Cuando agrego una nueva tarea valida
Entonces debería ver esta tarea en el listado

Escenario
: Agregar una tarea invalida
Cuando agrego una nueva tarea invalida
Entonces debería ver un mensaje de error

Historia de Usuario
Historia de Usuario
Historia de Usuario
Como un usuario debería poder marcar una tarea como completada y actualizar el listado
Escenario
: marcar una tarea como completada
Cuando
marque una tarea como completada
Entonces
la tarea debería removerse de la lista

Como usuario debería poder asignarle una prioridad a una tarea y poder mantener el registro de esta
Escenario
: Agregar una tarea con prioridad
Cuando
agregue una tarea con prioridad
Entonces
esta se debería ver en el listado

Como usuario debería poder filtrar las tareas por prioridad para poder encontrar las tareas con una prioridad determinada.
Escenario
: filtrar por prioridad
Cuando
selecciona una x prioridad,
debería
mostrar solo las tareas con esta propiedad

Reportes
it('should update the root name', function () {
var newRootName = 'root updated';

scope.selectNode(nodeRootTest, nodeRootTest);
nodeRootTest.newNodeName = newRootName;

scope.renameNode(nodeRootTest);

expect(nodeRootTest.label).toBe(newRootName);
});


Angular.js
nodeRootTest = {
"label": "project",
"id": "-1",
"type": "root",
"ext": "", "children": []
};
test\unit\projectNavigatorModule\projectNavigatorControllerSpec.js
AngularJS es un framework MVC de JavaScript para el Desarrollo Web Front End que permite crear aplicaciones SPA (Single-Page Applications)
it('should have a Widget List', function () {
expect(scope.widgetList).toBeDefined();
});

test\unit\dataModule\dataControllerSpec.js
beforeEach(inject(function ($rootScope, $controller, $filter, _storageService_) {
rootScope = $rootScope;
scope = rootScope.$new();
storageService = _storageService_;
dataController = $controller('dataController',
{ $scope: scope, $rootScope: $rootScope, $filter: $filter, storageService: storageService });
scope.resources = resources['enUs'];
}));
describe('Actions:', function () {
beforeEach(inject(function ($rootScope, $controller, _projectContentService_) {
scope = $rootScope.$new();
scope.resources = resources["enUs"];
rootScope = $rootScope;
projectContentService = _projectContentService_;
spyOn(projectContentService, 'getFileTree').andCallThrough();
projectNavigatortController = $controller('projectNavigatorController', { $scope: scope });

scope.project.fileTree = fileTreeTest;
}));

describe('Load File Tree:', function () {
it('should listen a load project event', function () {
var widgetName = 'newWidget';
rootScope.$emit(events.projectNavigatorController.loadProject, widgetName, []);
expect(scope.project.fileTree[0].label).toEqual(widgetName);
expect(scope.project.fileTree[0].children.length).toBe(0);
rootScope.$emit(events.projectNavigatorController.loadProject, widgetName, fileListTest);
expect(scope.project.fileTree[0].children.length).toBeGreaterThan(0);
});
it('should load the file tree', function () {
var tree = projectContentService.getFileTree(fileListTest);
scope.loadProject('WidgetName', fileListTest);
expect(projectContentService.getFileTree).toHaveBeenCalled();
expect(scope.project.fileTree[0].children).toEqual(tree);
});
test\unit\projectNavigatorModule\projectNavigatorControllerSpec.js
...
describe('Components:', function () {
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
scope.resources = resources["enUs"];
projectNavigatortController = $controller('projectNavigatorController',
{ $scope: scope,$rootScope: $rootScope, projectContentService: projectContentService });
}));

it('should have a file tree structure', function () {
expect(scope.project).toBeDefined();
expect(scope.project.fileTree).toBeDefined();

});

it('should have the current selected node', function () {
expect(scope.project.selectedNode).toBeDefined();
});

it('should have the current selected node parent', function () {
expect(scope.project.selectedNodeParent).toBeDefined();
});
test\unit\projectNavigatorModule\projectNavigatorControllerSpec.js
...
it('should call the free space function if there is no possible to save the changes', function () {
spyOn(storageService, 'addKey').andCallFake(function () {
return false;
});
spyOn(scope, 'freeSpace');

scope.saveAll(eventParams.actualFileList[1], 0, eventParams.done);

expect(scope.freeSpace).toHaveBeenCalled();

});
test\unit\dataModule\dataControllerSpec.js
beforeEach(function () {
propertiesTest = {
design: {
properties: {
property_test: {
'bas-type': 'boolean',
'caption': {
'default': ''
}
}
},
visual: {
'property-box': {
tabs: [
{
elements: [
{ value: 'property_test' }
]
}
]
}
}
},
runtime: {
properties: [
{
name: 'property_test'
},
{
metavalue: '<design:property_test/>'
}
]
}
};
test\unit\propertyModule\propertyControllerSpec.js
describe('Get', function () {
it('should save the file content in the properties object', function () {
var fileTest = {
content: angular.copy(angular.toJson(propertiesTest).replace('property-test', 'property-test1'))
};

scope.get(fileTest);

expect(scope.properties.design.properties['property-test1']).toEqual(propertiesTest.design.properties['property-test1']);
});
describe('Save', function () {
beforeEach(inject(function ($rootScope, $controller) {
rootScope = $rootScope;
scope = $rootScope.$new();
bizagiSDKController = $controller('bizagiSDKController', { $scope: scope, $rootScope: $rootScope });
}));
it('should listen a save event and call the save file function', function () {
spyOn(scope, 'saveFile');

scope.$emit(events.menuController.save);

expect(scope.saveFile).toHaveBeenCalled();
});
});
test\unit\bizagiSDKModule\bizagiSDKControllerSpec.js
Full transcript