9 votes

Couverture de code avec vue 2, typescript, mocha et karma

Nous utilisons Vue 2 en combinaison avec Typescript et webpack 3. Vuex est utilisé pour la gestion des états. Nos tests sont exécutés avec Karma ainsi que Mocha, Sinon, Expect et Avoriaz. Tout fonctionne bien mais j'essaie de faire fonctionner la couverture de code avec Istanbul pour avoir une meilleure représentation visuelle des tests manquants.

Petite représentation de la structure du dossier

  • src

    • composants
      • partagé
      • bouton
        • bouton.vue
        • button.ts
    • index.ts
    • ...
  • tests

    • unité
      • composants
        • partagé
        • bouton
          • bouton.spec.test.ts
    • karma.conf.js
    • karma.coverage.js
    • index.ts
    • ...

bouton.vue

<template>
    <button onClick="handleClick" visible="visible"></button>
</template>

<script lang="ts" src="./button.ts"></script>

button.ts

import { Component, Prop, Vue } from 'vue-property-decorator';

@Component({})
export default class Button extends Vue {

    @Prop({ default: false })
    public visible: boolean;

    private onClick() {
       // do stuff
    }
}

Actuellement, je n'ai même pas créé de button.spec.ts, ce que j'essaie de faire faire à l'équipe en utilisant ces informations, et voici le résultat de la couverture du code :

Code coverage

La couverture en général dans le projet :

✔ 332 tests completed
=============================== Coverage summary ===============================
Statements   : 43.88% ( 1847/4209 )
Branches     : 36.83% ( 952/2585 )
Functions    : 32.97% ( 456/1383 )
Lines        : 45.28% ( 1732/3825 )
================================================================================

Mais en général, les résultats ne montrent pas du tout la couverture du code. Chaque fichier est comme ceci :

Code lines

Mes questions

  • Comment puis-je obtenir un meilleur résultat ? Est-ce qu'il me manque quelque chose de fondamental concernant la couverture du code ?
  • Comment coder les fonctions de couverture qui ne sont exécutées que dans les fichiers .vue ?

D'autres fichiers qui pourraient être liés :

karma.coverage.js

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['mocha', 'chai', 'sinon'],
    files: [
      'index.ts'
    ],
    reporters: reporters,
    preprocessors: {
      'index.ts': ['webpack']
    },
    webpack: webpackConfig,
    webpackServer: {
      noInfo: true
    },
    junitReporter: {
      outputDir: 'reports/'
    },
    coverageReporter: {
      reporters: [{
        type: 'json',
        dir: '../../coverage/',
        subdir: '.'
      },
      {
        type: 'text-summary'
      },
    ]
    },
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: ['PhantomJS_custom'],
    customLaunchers: {
        'PhantomJS_custom': {
            base: 'PhantomJS',
            options: {
                windowName: 'my-window',
                settings: {
                    webSecurityEnabled: false
                },
            },
            flags: ['--remote-debugger-port=9003', '--remote-debugger-autorun=yes'],
            debug: false
        }
    },
    phantomjsLauncher: {
        // Have phantomjs exit if a ResourceError is encountered (useful if karma exits without killing phantom)
        exitOnResourceError: true
    },
    mime: {
      'text/x-typescript': ['ts']
    },
    singleRun: true,
    concurrency: Infinity
  });
};

unité/index.ts

import 'babel-polyfill';
import Vue from 'vue';

Vue.config.productionTip = false;

function requireAll(r: any): any {
    r.keys().forEach(r);
}

requireAll((require as any).context('./', true, /spec.ts$/));
requireAll((require as any).context('../../src/', true, /^(?!.*(main)).*ts$/));

2voto

yariash Points 18

Je suggère que vous utilisiez vue-unité .

Par exemple, votre scénario de test pourrait ressembler à ceci :

import { beforeEachHooks, afterEachHooks, mount, waitForUpdate, simulate } from 'vue-unit'
import Button from '@/components/Button'

describe('Button', () => {
  beforeEach(beforeEachHooks)

 it('should render with hidden class if visible is set to false', () => {
     const vm = mount(Button, {
         visible: false //you can ass properties
     })

     expect(vm.$el).to.have.class('hidden') //example assertions, needs chai-dom extension
  })

  afterEach(afterEachHooks)
})

Vous pouvez également vérifier le résultat des méthodes individuelles :

 const vm = mount(Button)

 expect(vm.$el.somemethod('val')).to.be('result')
 //method declared in methods block

Vous devriez également envisager d'ajouter des extensions au chai, telles que chai-dom ou sinon-chai ce qui vous permettrait de créer des assertions plus souples :

it('should invoke onClick handler when button is clicked', () => {
    const spy = sinon.spy()

    const vm = mount(Button, {
      onClick: spy
    })

    simulate(vm.$el, 'click')

    expect(spy).to.be.called
  })

Vous pouvez le configurer dans karma.conf.js :

//karma.conf.js
...
frameworks: ['mocha', 'chai-dom', 'sinon-chai', 'phantomjs-shim'],
...

IMHO Votre configuration de couverture de code semble bonne, donc si vous ajoutez des tests pour vos composants, cela devrait booster vos statistiques.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X