Escrever testes de unidade em TypeScript (pelo exemplo de gatos)

Como faço para escrever testes de unidade em um projeto TypeScript? Neste artigo, tentarei responder a essa pergunta e também mostrarei como criar um ambiente de teste de unidade para projetos usando TypeScript.





O que são testes de unidade?

Testes de unidade - testes aplicados em diferentes camadas de um aplicativo que testam a menor lógica divisível em um aplicativo: por exemplo, um módulo, classe ou 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 você pode ver, nossa cobertura não está completa, as linhas 11-15 permaneceram sem teste. Esses são apenas os métodos da classe Cat move



esay.







Adicionamos mais dois testes para esses métodos e terminamos com um arquivo com testes:





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');
  }
}
      
      



Execute nossos testes novamente e veja se a classe Cat agora tem cobertura total de teste.





Resultado

Como resultado, criamos uma infraestrutura de teste para nosso aplicativo e agora podemos cobrir qualquer novo módulo ou classe com testes, verificando se o código existente não foi quebrado.





PS: Baseado no artigo Como configurar o teste de unidade com TypeScript .








All Articles