# Testes Vitruvio

## Objetivo

Permitir testes tecnicos em Rhino ES5 usando libs do proprio Vitruvio, carregadas por `libService.loadScript(...)`, sem depender de Node ou de arquivos fora do runtime da plataforma.

## Lib principal

Use a lib [Vitruvio/Libs/vitruvio_test.js](../Libs/vitruvio_test.js).

Ela expoe tres formas de execucao:

1. `executarSuitePorSigla(siglaSuite, manifest)`
2. `executarSuitesPorSigla(siglas, manifest)`
3. `executarRotinaPorSigla(siglaRotina, metodoRegistro, manifest)`

## Modelo recomendado

1. A rotina real fica na lib produtiva.
2. Os testes ficam em outra lib, separados por funcionalidade.
3. O painel, processo ou formulario chama a lib de testes por sigla quando voce quiser validar.

## Suite separada por sigla

Cada suite deve exportar `registrar(runner, opcoes)`.

Exemplo real: [Vitruvio/Libs/test_nfse_relatorio.js](../Libs/test_nfse_relatorio.js)

```javascript
function MinhaSuite() {
   this.registrar = function (runner, opcoes) {
      runner.describe('Minha funcionalidade', {
         rotina: 'minha_rotina',
         funcionalidade: 'fluxo_principal',
         tags: ['smoke', 'unit']
      }, function () {
         runner.it('executa fluxo feliz', function () {
            runner.expect(true).toBe(true);
         });
      });
   };
}

module.exports = new MinhaSuite();
```

## Testes na propria lib da rotina

Se preferir manter os testes na mesma lib da rotina, exponha um metodo como `registrarTestes`.

```javascript
function MinhaRotina() {
   this.executar = function () {
   };

   this.registrarTestes = function (runner) {
      runner.describe('MinhaRotina', {
         rotina: 'minha_rotina',
         funcionalidade: 'validacao_basica',
         tags: ['unit']
      }, function () {
         runner.it('valida comportamento basico', function () {
            runner.expect(1).toBe(1);
         });
      });
   };
}

module.exports = new MinhaRotina();
```

## Como rodar em painel, initScript ou processo

### Rodando uma suite separada

```javascript
importClass(Packages.br.com.davinti.base.vaadin.components.layout.MessageBox);

function run() {
   var vt = libService.loadScript('vitruvio_test');
   var report = vt.executarSuitePorSigla('test_nfse_relatorio', {
      tags: ['smoke'],
      funcionalidades: ['acao_relatorio'],
      failFast: true,
      contexto: {
         itemId: 98765
      }
   });

   MessageBox.show('Resultado dos testes', vt.formatarRelatorio(report));
}
```

### Rodando testes da propria rotina

```javascript
var vt = libService.loadScript('vitruvio_test');
var report = vt.executarRotinaPorSigla('minha_rotina', 'registrarTestes', {
   tags: ['unit']
});

println(vt.formatarRelatorio(report));
```

## Exemplo com NFSe

Foi adicionada a suite [Vitruvio/Libs/test_nfse_relatorio.js](../Libs/test_nfse_relatorio.js), separada da lib produtiva.

Tambem foram adicionados helpers testaveis em [Vitruvio/Libs/lib_nfse.js](../Libs/lib_nfse.js):

1. `criarDependenciasRelatorioPainel(dependencias)`
2. `montarNomeArquivoRelatorio(nomeBase, dependencias)`
3. `abrirRelatorioPainel(itemId, dependencias)`

Isso permite testar a funcionalidade de Relatorio do painel sem acoplar o teste ao XML.

## Matchers e spies disponiveis

Matchers:

1. `toBe`
2. `toEqual`
3. `toBeTruthy`
4. `toBeFalsy`
5. `toContain`
6. `toHaveLength`
7. `toThrow`
8. `toHaveBeenCalled`
9. `toHaveBeenCalledTimes`
10. `toHaveBeenCalledWith`
11. `not`

Spies:

1. `runner.fn()`
2. `runner.spy(nome, implementacao)`
3. `runner.spyOn(obj, metodo)`

## Recomendacao pratica

1. deixe o XML fino
2. mova a regra para uma lib
3. injete dependencias quando a funcionalidade falar com `engine`, `downloadutil`, `vReportService`, `db` ou outros servicos
4. mantenha suites separadas por funcionalidade quando a rotina crescer
5. rode testes por botao temporario, initScript controlado ou painel de homologacao