Escribir pruebas unitarias en TypeScript (con el ejemplo de gatos)

驴C贸mo escribo pruebas unitarias en un proyecto de TypeScript? En este art铆culo intentar茅 responder esta pregunta y tambi茅n mostrarle c贸mo crear un entorno de prueba unitaria para proyectos que utilizan TypeScript.





驴Qu茅 son las pruebas unitarias?

Pruebas unitarias: pruebas aplicadas en diferentes capas de una aplicaci贸n que prueban la l贸gica divisible m谩s peque帽a en una aplicaci贸n: por ejemplo, un m贸dulo, clase o m茅todo.





, , , () .





. , . . , , . .





. :





project
| node_modules
| src
| package.json
| tsconfig.json
      
      



./src



cat.module.ts



Cat.





export class Cat {
  public name: string;
  public color: string;

  constructor(name: string, color: string) {
    this.name = name;
    this.color = color;
  }

  public move(distanceMeter: number) : string {
    return `${this.name} moved ${distanceMeter}m.`;
  }

  public say() : string {
    return `Cat ${this.name} says meow`;
  }
}
      
      



, . (SUT - system under test).





, test, .





npm :





npm install --save-dev ts-node mocha @testdeck/mocha nyc chai @types/chai







:

ts-node



- TypeScript REPL node.js.





mocha



- , , . . @testdeck/mocha



- testdeck , .





nyc



- CLI Istanbul, .





chai



- (assertions), . . @types/chai



typescript'





, test



, tsconfig.json



, TS .





{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "baseUrl": "./",
    "module": "commonjs",
    "experimentalDecorators": true,
    "strictPropertyInitialization": false,
    "isolatedModules": false,
    "strict": false,
    "noImplicitAny": false,
    "typeRoots" : [
      "../node_modules/@types"
    ]
  },
  "exclude": [
    "../node_modules"
  ],
  "include": [
    "./**/*.ts"
  ]
}
      
      



include test .ts





, register.js



ts-node, .





const tsNode = require('ts-node');
const testTSConfig = require('./test/tsconfig.json');

tsNode.register({
  files: true,
  transpileOnly: true,
  project: './test/tsconfig.json'
});
      
      



, .mocharc.json



, :





{
  "require": "./register.js",
  "reporter": "list"
}
      
      



.nyrc.json



.





{
  "extends": "@istanbuljs/nyc-config-typescript",
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules/"
  ],
  "extension": [
    ".ts"
  ],
  "reporter": [
    "text-summary",
    "html"
  ],
  "report-dir": "./coverage"
}
      
      



, :





project
| node_modules
| src
| test
| --- tsconfig.json
| .mocharc.json
| .nyrc.json
| package.json
| register.js
| tsconfig.json
      
      



package.json







"test": "nyc ./node_modules/.bin/_mocha 'test/**/*.test.ts'"
      
      



,





./test



cat.unit.test.ts



:





import { Cat } from '../src/cat.module';
import { suite, test } from '@testdeck/mocha';
import * as _chai from 'chai';
import { expect } from 'chai';

_chai.should();
_chai.expect;

@suite class CatModuleTest {
  private SUT: Cat;
  private name: string;
  private color: string;

  before() {
    this.name = 'Tom';
    this.color = 'black';
    this.SUT = new Cat(this.name, this.color);
  }
}
      
      



Cat cat.module.ts



, , .





before Cat, .





, .





import { Cat } from '../src/cat.module';
import { suite, test } from '@testdeck/mocha';
import * as _chai from 'chai';
import { expect } from 'chai';

_chai.should();
_chai.expect;

@suite class CatModuleTest {
  private SUT: Cat;
  private name: string;
  private color: string;

  before() {
    this.name = 'Tom';
    this.color = 'black';
    this.SUT = new Cat(this.name, this.color);
  }

  @test 'Cat is created' () {
    this.SUT.name.should.to.not.be.undefined.and.have.property('name').equal('Tom');
  }
}
      
      



npm test :





Como puede ver, nuestra cobertura no est谩 completa, las l铆neas 11 a 15 quedaron sin probar. Estos son solo los m茅todos de la clase Cat move



ysay.







Agregamos dos pruebas m谩s para estos m茅todos y terminamos con un archivo de este tipo con pruebas:





import { Cat } from '../src/cat.module';
import { suite, test } from '@testdeck/mocha';
import * as _chai from 'chai';
import { expect } from 'chai';

_chai.should();
_chai.expect;

@suite class CatModuleTest {
  private SUT: Cat;
  private name: string;
  private color: string;

  before() {
    this.name = 'Tom';
    this.color = 'black';
    this.SUT = new Cat(this.name, this.color);
  }

  @test 'Cat is created' () {
    this.SUT.name.should.to.not.be.undefined.and.have.property('name').equal('Tom');
  }

  @test 'Cat move 10m' () {
    let catMove = this.SUT.move(10);
    expect(catMove).to.be.equal('Tom moved 10m.');
  }

  @test 'Cat say meow' () {
    expect(this.SUT.say()).to.be.equal('Cat Tom says meow');
  }
}
      
      



Ejecute nuestras pruebas nuevamente y vea que la clase Cat ahora tiene una cobertura de prueba completa.





Salir

Como resultado, hemos creado una infraestructura de prueba para nuestra aplicaci贸n y ahora podemos cubrir cualquier nuevo m贸dulo o clase con pruebas, verificando que el c贸digo existente no se haya roto.





PD: Basado en el art铆culo C贸mo configurar la prueba unitaria con TypeScript .








All Articles