Skip to content

Latest commit

 

History

History
837 lines (652 loc) · 41.9 KB

File metadata and controls

837 lines (652 loc) · 41.9 KB

shieldsIO shieldsIO shieldsIO

WideImg

POO con JS, ECMA6, Patrones de diseño, AJAX avanzado, HTML5 avanzado, APIs externas.

Clase 23

img

Code Review

img

Revisión de código es la examinación sistemática (como en la revisión por pares) del código fuente de un programa informático. Se practica con el objetivo de mejorar la calidad del código que se genera en el proceso de desarrollo del software, mediante la detección temprana de errores en el código de los programas o alternativas más eficientes a la implementación inicial. También se utiliza como técnica para mejorar las cualidades de los desarrolladores involucrados en la práctica, mediante la discusión abierta de posibles mejoras en el programa.

Se realizan principalmente revisiones de código por parte de las metodologías ágiles que practican programación en pareja como parte del proceso, o en otras que pueden implementar revisiones periódicas de código, tanto informales como formales. Wikipedia

Las claves

  • Forma parte de algunas metodologías ágiles
  • Mejora la comunicación y la calidad del grupo
  • No culpar a nadie, ni tomarselo personal
  • La culpa de un bug es ahora compartida
  • Se sugieren los cambios y se discuten

¿Que revisar?

  • Arquitectura/Diseño (patrones, errores potenciales, manejo de errores, eficiencia...)
  • Estilo (Longitudes, legibilidad, nombres...)
  • Testing (Cobertura, mocks, etc...)

Herramientas

Pair coding

IMG

La Programación en Pareja (o Pair Programming en inglés) requiere que dos programadores participen en un esfuerzo combinado de desarrollo en un sitio de trabajo. Cada miembro realiza una acción que el otro no está haciendo actualmente: Mientras que uno codifica las pruebas de unidades el otro piensa en la clase que satisfará la prueba, por ejemplo.

La persona que está haciendo la codificación se le da el nombre de controlador mientras que a la persona que está dirigiendo se le llama el navegador. Se sugiere a menudo para que a los dos socios cambien de papeles por lo menos cada media hora o después de que se haga una prueba de unidad. Wikipedia

Lo bueno

  • Mejor código
  • Equipo más fuerte y cohesionado
  • Se aprende mucho más
  • Mejora la propiedad colectiva del código
  • Mejora las habilidades sociales
  • Reduce el número de bugs

Lo malo

  • No todo el mundo se siente cómodo
  • No es facil juntar niveles distintos
  • Es dificil combinar tiempos (balance, vida personal, etc....)
  • Es más dificil en remoto
  • Los tiempos de desarrollo son distintos

QA

img

Las claves

  • Persona especializada en asegurar la calidad del proyecto
  • Se encarga del diseño y ejecucción de pruebas
  • Se encarga de validar la caldiad técnica (rendimeinto, optimización, etc...)
  • Define standares, medidas y metricas que debemos cumplir
  • Revisa y mantiene seguimiento de la calidad
  • Coordina el testeo
  • Las funciones pueden cambiar entre proyectos y empresas

Recursos

Testing

IMG

Las pruebas de software (en inglés software testing) son las investigaciones empíricas y técnicas cuyo objetivo es proporcionar información objetiva e independiente sobre la calidad del producto a la parte interesada o stakeholder. Es una actividad más en el proceso de control de calidad. Wikipedia

Tipos de pruebas

  • Estáticas, No necesitan ejecutar código alguno
  • Dinámicas, que requieren ejecucción de código

Según su ejecucción

  • Manuales, requieren de nuestra interacción para funcionar
  • Automáticas, la propia máquina es capaz de relaizar las pruebas sin sufrir alteraciones

Según el enfoque

  • Caja Blanca, nos centramos en el funcionamiento interno de las cosas
  • Caja Negra, nos centramos en las entradas (input) y salidas (output) de las clsas y no en su funcionamiento
  • Pruebas aleatorias, variante de la caja negra donde el input es aletorio

Testing: ¿Qué podemos testear?

Testing: ¿Que testeamos en JavaScript?

  • Unit Testing
  • Integration testing
  • End-To-End Testing (e2e)
  • Alpha & Beta Testing
  • Accessibility testing
  • Security Testing
  • Stress Testing & Load Testing
  • A/B testing

TDD

img

Desarrollo guiado por pruebas de software, o Test-driven development (TDD) es una práctica de ingeniería de software que involucra otras dos prácticas: Escribir las pruebas primero (Test First Development) y Refactorización (Refactoring). Para escribir las pruebas generalmente se utilizan las pruebas unitarias (unit test en inglés). En primer lugar, se escribe una prueba y se verifica que las pruebas fallan. A continuación, se implementa el código que hace que la prueba pase satisfactoriamente y seguidamente se refactoriza el código escrito. El propósito del desarrollo guiado por pruebas es lograr un código limpio que funcione. La idea es que los requisitos sean traducidos a pruebas, de este modo, cuando las pruebas pasen se garantizará que el software cumple con los requisitos que se han establecido. Wikipedia

Las claves

  • Implementar solo lo necesario
  • Evitar bugs a toda costa
  • Creamos software modular y reutilizable
  • No tener miedo de tocar "legacy"

El Ciclo de desarrollo

  • Elegir un requisito
  • Escribir las pruebas
  • Verificar que fallan las pruebas
  • Escribir suficiente código para pasar las preubas
  • Pasar las pruebas
  • Refactorizar y pasar las pruebas (hasta estar listo)
  • El requisito ha sido implementado

Filosofías derivadas

Recursos

Piramide de Test creada por Mike Cohn

IMG

Testing en la práctica

testing_graph

Las claves

  • Código que verifica el funcionamiento de otro código.
  • Deben poder realizarse de manera automática.
  • Cubrir mayor cantidad de código posible.
  • Independientes entre si.
  • Capaces de ejercutarse infinidad de veces.
  • Pueden agruparse en Test Suites.
  • Uso de colores y mensajes claros.
  • A guide to unit testing in JavaScript

Ejemplo: Versión Browser

// Función
function sumar (p1, p2){
  return p1 + p2;
}

// Test
function testSumar(){
  if (sumar(1, 2) !== 3) {
    document.write('<p style="color: red;">sumar(1, 2) ERROR - No devuelve 3</\p>');
  } else {
    document.write('<p style="color: green;">sumar(1, 2) OK</p>');
  }

  if (sumar("2", 2) !== 4) {
    document.write('<p style="color: red;">sumar("2", 2) ERROR - No devuelve 4</p>');
  } else {
    document.write('<p style="color: green;">sumar("2", 2) OK</p>');
  }
}

Ejemplo: Versión Node.js

const chalk = require('chalk');
const log = console.log;

// Función
function sumar (p1, p2){
  return p1 + p2;
}

// Test
function trueAssert(msg) {
    log(chalk.bgGreen.white(msg))
}

function falseAssert(msg) {
    log(chalk.bgRed.white(msg))
}

function testSumar(){
  if (sumar(1, 2) !== 3) {
    falseAssert("sumar(1, 2) ERROR")
  } else {
    trueAssert("sumar(1, 2) OK")
  }

  if (sumar("2", 2) !== 4) {
    falseAssert('sumar("2", 2) ERROR - No devuelve 4')
  } else {
    trueAssert('sumar("2", 2) OK')
  }
}

testSumar();

Usando console.assert

IMG

const controlador = false;
console.assert(controlador, "\"controlador\" es igual a \"false\"");

Assert Nodejs

const assert = require('assert');

assert.equal(1, 1);     // OK, 1 == 1
assert.equal(1, '1');   // OK, 1 == '1'
assert.equal(1, 2);     // AssertionError: 1 == 2

assert.equal({ a: { b: 1 } }, { a: { b: 1 } }); 
// AssertionError: { a: { b: 1 } } == { a: { b: 1 } }

Assertion Testing

Frameworks de testing

BDD/TDD

  • MochaJS - ☕️ simple, flexible, fun javascript test framework for node.js & the browser
  • Jasmine - Simple JavaScript testing framework for browsers and node.js
  • Intern - Intern. Software testing for humans.
  • Chai- BDD / TDD assertion framework for node.js and the browser that can be paired with any testing framework.
  • Ava - 🚀 Futuristic JavaScript test runner

BDD

Test Runners

  • Karma - Spectacular Test Runner for JavaScript
  • Jest - 🃏 Delightful JavaScript Testing.
  • GlaceJS - glace-core is a quick-start functional & unit testing framework based on mocha and extensible with plugins (how plugins work).
  • Apickli - apickl. REST API integration testing framework based on cucumber.js

Spies, Stubs & Mock frameworks

  • Sinon.JS - Test spies, stubs and mocks for JavaScript.
  • JSMockito - Javascript mocking framework inspired by the awesome mockito
  • Apimocker - node.js module to run a simple http server for mock service responses.
  • Rewire - Easy monkey-patching for node.js unit tests
  • Enzyme - JavaScript Testing utilities for React
  • Testdouble - A minimal test double library for TDD with JavaScript

Code analysis

  • ESLint - A fully pluggable tool for identifying and reporting on patterns in JavaScript
  • JsHint - JSHint is a tool that helps to detect errors and potential problems in your JavaScript code
  • JsLint - The JavaScript Code Quality Tool

Performance & stress & load

  • k6 - A modern load testing tool, using Go and JavaScript
  • Artillery - Flexible and powerful toolkit for load and functional testing. HTTP, Socket.io, WebSockets, Kinesis, HLS. Make your systems indestructible! 👩‍💻 🏰
  • LoadComplete - Load Testing Tool for Websites and Web Apps

Security checking

  • OWASP Glue - Application Security Automation
  • OWASP ZAP - The OWASP ZAP core project
  • BeEF - Manipulate the browser exploiting any XSS vulns you find

Reporting

  • ReportPortal.io - AI-powered Test Automation Dashboard
  • Istanbul - Yet another JS code coverage tool that computes statement, line, function and branch coverage with module loader hooks to transparently add coverage when running tests. Supports all JS coverage use cases including unit tests, server side functional tests and browser tests. Built for scale.
  • Blanket - blanket.js is a simple code coverage library for javascript. Designed to be easy to install and use, for both browser and nodejs.
  • Mochawesome - A Gorgeous HTML/CSS Reporter for Mocha.js
  • allure - There are lots of cool testing frameworks for different programming languages. Unfortunately only a few of them can provide good representation of test execution output. The Yandex testing team is working on Allure - an open-source framework designed to create test execution reports that are clear to everyone in the team.

Qunit

Qunit

Las Claves

  • Facil y sencillo
  • Ideal para empezar
  • No contiene muchos plugins
  • Originalmente creado para testear JQuery

Implementacion en browser

fichero index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>QUnit Example</title>
  <link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.6.2.css">
</head>
<body>
  <div id="qunit"></div>
  <div id="qunit-fixture"></div>
  <script src="https://code.jquery.com/qunit/qunit-2.6.2.js"></script>
  <script src="tests.js"></script>
</body>
</html>

fichero test.js

QUnit.test( "hello test", function( assert ) {
  assert.ok( 1 == "1", "Passed!" );
});

Implementación en Nodejs

npm install --save-dev qunit

Ejemplo

// Función
function sumar (p1, p2){
return p1 + p2;
}

// Test
test("test de la funcion sumar(p1, p2)", function() {
equal(sumar( 1, 2), 3, "1 + 2 = 3" );
notEqual(sumar( "2", 2), "4", " 2(cadena) + 2 != 4(cadena) ");
});

Documentación

API - Main methods

API - Assertions

API - Config

API - Callbacks

API - Async Control

Mocha & Chai

Mocha

Las claves

Las interfaces de Chai

//Assert: 
assert.typeOf( cadena, 'string', 'cadena es un string' );

//Expect: 
expect( cadena ).to.be.a( 'string' );

//Should: 
cadena.should.be.a( 'string' );

Chai plugins

  • chai-semver - Semver plugin for Chai
  • chai-fs - Chai assertion plugin for the Node.js filesystem API. Uses path and synchronous fs to assert files and directories.
  • Chai Events - Make assertions about event emitters.
  • Chai HTTP - HTTP integration testing with Chai assertions.
  • chai-spy - 🔎 Spies for the Chai Assertion Library
  • Chai Assertions for RxJS Observables - ChaiRx extends Chai with a simple utility method emit for testing emits from an RxJS Observable stream using the Rx.TestScheduler.
  • chai-moment-string - chai plugin for validating a string with an expected moment format
  • chai-fireproof - Chai assertions and helpers for Firebase and Fireproof.
  • chai-eventemitter - This is a plugin for chai to simplify the testing of EventEmitter.
  • Chai Spies - It provides the most basic function spy ability and tests.
  • Sinon.JS Assertions for Chai - Sinon–Chai provides a set of custom assertions for using the Sinon.JS spy, stub, and mocking framework with the Chai assertion library. You get all the benefits of Chai with all the powerful tools of Sinon.JS.
  • chai-url - A chai assertion plugin for working with urls
  • chai-dom - chai-dom is an extension to the chai assertion library that provides a set of assertions when working with the DOM (specifically HTMLElement and NodeList)
  • In-Order Sinon-Chai Assertions - Sinon-Chai provides Chai assertions for Sinon.JS. Unfortunately, it does not deal with making sure a spy was called multiple time in a specific order.

Ejemplo

// Función
function sumar (p1, p2){
return p1 + p2;
}

// Test
mocha.setup('bdd');
const expect = chai.expect;
const should = chai.should();
describe("Test de la funcion sumar(p1, p2)", () => {

it('1 + 2 = 3', () => {
  expect(sumar( 1, 2)).to.equal(3);
});

it('\"2\" + 2 != \"4\"', () => {
  expect(sumar( "2", 2)).not.equal("4");
});

});

mocha.run();

Documentación

Sinon

IMG

Documentación

Ejemplo

// Función
function getTodos(listId, callback) {
    jQuery.ajax({
        url: '/todo/' + listId + '/items',
        success: function (data) {
            // Node-style CPS: callback(err, data)
            callback(null, data);
        }
    });
}

// Testing
after(function () {
    // When the test either fails or passes, restore the original
    // jQuery ajax function (Sinon.JS also provides tools to help
    // test frameworks automate clean-up like this)
    jQuery.ajax.restore();
});

it('makes a GET request for todo items', function () {
    sinon.replace(jQuery, 'ajax', sinon.fake());
    getTodos(42, sinon.fake());

    assert(jQuery.ajax.calledWithMatch({ url: '/todo/42/items' }));
});

Aprendiendo testing en JS y Node

IMG

Recursos

End To End (E2E) con Nodejs

IMG

Librerías Clásicas

  • WebDriverJs - WebDriverJs is the Official javascript implementation of selenium. It uses to Selenium’s Json-wire-protocol to interact with browser. It is written by selenium guys.
  • WebdriverIO - Webdriver IO is a selenium wrapper written in javascript and runs on node.js. It is a custom implementation of W3C webdriver protocol.
  • Protractor - Protractor is an End-to-End test framework for Angular Js applications. It is packaged under npm and runs on NodeJs.
  • Nightwatch.js - Nightwatch.js is a Node.js based End-to-End (E2E) testing solution. It uses the powerful W3C WebDriver API to perform actions on DOM elements.
  • Dalek.js - Automated cross browser testing with JavaScript
  • Nemo - Launch your web sites & applications with confidence
  • TestCafe - A node.js tool to automate end-to-end web testing
  • Nightmare - A high-level browser automation library.
  • Hermione - Browser test runner based on mocha and wdio
  • Chromeless - 🖥 Chrome automation made simple. Runs locally or headless on AWS Lambda.
  • Chrominator - high level api to the chrome remote debugger
  • Chromy - Chromy is a library for operating headless chrome. 🍺🍺🍺
  • Navalia - A bullet-proof, fast, and reliable headless browser API
  • Lambdium - headless chrome + selenium webdriver in AWS Lambda using the serverless application model
  • GhostJS - ghostjs provides modern UI testing with async functions
  • CasperJS - Navigation scripting & testing for PhantomJS and SlimerJS
  • Cypress.io - Fast, easy and reliable testing for anything that runs in a browser.

Recursos

La revolución

img

Uso soluciones clásicas (Selenium, etc...)?

  • Necesito testear en más de un navegador
  • Necesito testear en un único navegador pero no es Chrome

Uso Puppeteer?

Otros Test con Nodejs

Librerias y utlilidades

  • Supertest - Super-agent driven library for testing node.js HTTP servers using a fluent API
  • Faker.js - generate massive amounts of fake data in Node.js and the browser
  • Frisby - The Easiest REST API Testing Framework Out There
  • Gemini - Gemini is a utility for regression testing the visual appearance of web pages.
  • Gremlins.js - Monkey testing library for web apps and Node.js
  • Mailosaur - Mailosaur Node.js Client Library
  • Differencify - Differencify is a library for visual regression testing
  • CodeceptJS - Modern era acceptance testing for Nodejs

Benchmarking

img

Librerias

  • Benchmark.js - Benchmarking library that supports high-resolution timers and returns statistically significant results.
  • matcha - Simplistic approach to benchmarking.

Ejemplo

const suite = new Benchmark.Suite;

// add tests
suite.add('RegExp#test', () => {
  /o/.test('Hello World!');
})
.add('String#indexOf', () => {
  'Hello World!'.includes('o');
})
.add('String#match', () => {
  !!'Hello World!'.match(/o/);
})
// add listeners
.on('cycle', event => {
  console.log(String(event.target));
})
.on('complete', function() {
  console.log(`Fastest is ${this.filter('fastest').pluck('name')}`);
})
// run async
.run({ 'async': true });

Mobile test automation

IMG

Librerías

UI test automation

IMG

Librerías

Ejercicios

1 - Inicializa un repositorio utilizando npm y git. Deberás preparar un entorno básico de testing siguiendo los siguientes patrones:

  • Crea un directorio lib/ donde irá el código de tu proyecto.
  • Crea un directorio tests/ donde irán las pruebas unitarias.
  • En el package.json se debe crear el script test para que se ejecuten los tests del proyecto.
  • Cuando ejecutes los tests (utilizando mocha + chai) se deben ejecutar todos los ficheros en el directorio tests/.

Solución

2 - Aplicando TDD y utilizando el repositorio del ejercicio anterior, crea una función atm que devuelva el número más eficiente de billetes dados los siguientes casos:

  • Si un valor no es válido (ej. negativo) no debe devolver nada.
  • La función debe devolver billetes de entre 5 y 50€.

Ejemplo (5€)

  • 1 billete de 5€.

Ejemplo (35€)

  • 1 billete de 5€.
  • 1 billete de 10€.
  • 1 billetes de 20€.

Ejemplo (165€)

  • 1 billete de 5€.
  • 1 billete de 10€.
  • 3 billetes de 50€.

Solución

3 - Crea una función que acepte como primer argumento un número. Esa función debe devolver un objeto con los métodos add() y subtract(), y a su vez esos métodos se podrán ir encadenando hasta el infinito.

  • Cuando se llame a la función add(), tendrá que imprimir por consola el número anterior +1.
  • Cuando se llame a la función subtract(), tendrá que imprimir por consola el número anterior -1.

Ejemplo:

function createNumber() {
  // return ...
}

createNumber(5)   // prints "5"
  .add()          // prints "6"
  .add()          // prints "7"
  .subtract()     // prints "6"
  .add()          // prints "7"
  // ...

Solución

4 - Testea la siguiente función utilizando sinon.js y sinon-chai:

function getFilm(id, adapter) {
  const url = `https://ghibliapi.herokuapp.com/films/${id}`;
  
  if (!id) {
    throw new Error('ID not exists');
  }

  return adapter(url).then((json) => {
    return json.title;
  });
}

Solución