Как увеличить покрытие кода с помощью istanbul в node.js - PullRequest
0 голосов
/ 18 сентября 2018

Я использую Istanbul для покрытия кода, но получаю очень низкий процент покрытия, особенно в файле Models.

Рассмотрим следующий файл модели:

ModelA.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
var app = require('../server')
var db = require('../db/dbConnection');
var config = require('../configs/config')

    const Schema1 = new Schema({ 'configurations': [] });
    exports.save = function (aa, data, callback) {
        var logMeta = {
            file: 'models/modelA',
            function: 'save',
            data: {},
            error: {}
        }    
        if (!aa) {
            return callback('aa is required')
        }
        global.logs[aa].log('info', 'AA: ' + aa, logMeta);   

        db.connectDatabase(aa, function(error, mongoDB){    
            if(error){            
                logMeta.data['error'] = error
                global.logs[aa].log('error', 'error', logMeta);
                return callback(error)
            }

            const ModelA = mongoDB.model('bbb', cccc);                 
            ModelA.findOneAndUpdate({}, data, {upsert: true, new: true, runValidators: true}, function(error ,result){
                if (error) {   
                    logMeta.data['error'] = error
                    global.logs[aa].log('error', 'error', logMeta);
                }
                else {
                    logMeta.data = {}
                    logMeta.data['result'] = JSON.parse(JSON.stringify(result))
                    global.logs[aa].log('info', 'result', logMeta);
                }  
                callback(error, result);    
            });           
        })
    }

TestA.js:

var should = require('should'),
    sinon = require('sinon'),    
    ModelA= require("../models/ModelA");


    describe('Model test', function () {
        it('Should save Model', function (done) {
            var todoMock = sinon.mock(new ModelA({'configurations': []}));
            var todo = todoMock.object;

            todoMock
            .expects('save')
            .yields(null, 'SAVED');

            todo.save(function(err, result) {
                todoMock.verify();
                todoMock.restore();
                should.equal('SAVED', result, "Test fails due to unexpected result")
                done();
            });
        });
    });

Но я получаю процент кодового покрытия 20. ТАК, как я могу увеличить процент:

Also:

1. Должен ли я издеваться над db.connectDatabase, если да, как я могу достичь этого?

  1. Нужно ли мне использовать TestDb для запуска всего моего UnitTest? Или мне нужно assert ??

  2. Покрытие кода будет работать для модульного теста или интеграционного теста ???

Пожалуйста, поделитесь своими идеями. Спасибо

1 Ответ

0 голосов
/ 18 сентября 2018

Я использовал код от Istanbul до 100% для большинства моих клиент-серверных проектов, поэтому у меня могут быть ответы, которые вы ищете.

Как это работает

Всякий раз, когда вам требуется какой-либо локальный файл, он оборачивается повсеместно, чтобы понять, достигается ли каждая его часть вашим кодом.

Не только нужный файл испорчен, но и ваш текущий тест тоже. Однако несмотря на то, что код, охватывающий работающий тестовый файл, легко описать, макетированные классы и их код могут никогда не выполняться.

todoMock.expects('save')

В соответствии с Документация Sinon :

Переопределяет todo. save с помощью фиктивной функции и возвращает ее.

Если Istanbul испортит реальный метод save, ничего внутри этой области никогда не будет достигнуто, так что вы на самом деле тестируете, что имитация работает, а не то, что ваш реальный код делает.

Это должно ответить на ваш вопрос: Покрытие кода будет работать для модульного теста или интеграционного теста ???

Ответ в том, что он охватывает код, и это единственное, что вас интересует с точки зрения покрытия кода. Покрытие Sinon JS - это ничья цель.

Не нужно утверждать ... но

Как только вы поймете, как работает Istanbul, вы, естественно, поймете, что не имеет значения, если вы assert или нет, все, что вам нужно, - это чтобы вы достигли кода на самом деле и выполнили его.

Утверждение - это всего лишь ваша защита от сбоев, а не механизм, интересный сам по себе в любом Istanbul тесте. Когда ваше утверждение терпит неудачу, ваш тест тоже делает, так что вам полезно знать, что что-то не работает, и нет необходимости продолжать тестировать остальную часть кода (ранние ошибки, более быстрые исправления).

Придется ли вам издеваться над базой данных db.connect

Да, по крайней мере, для кода, который вы разместили. Вы можете назначить db как макет универсального объекта для контекста global и expect вызываемых методов, но вы также можете упростить свою жизнь, написав это:

function createDB(err1, err2) {
  return {
    connectDatabase(aa, callback) {
      callback(err1, {
        model(name, value) {
          return {
            findOneAndUpdate($0, $1, $3, fn) {
              fn(err2, {any: 'object'});
            }
          };
        }
      });
    }
  };
}

global.db = createDB(null, null);

Этот код в вашем тестовом файле можно использовать для создания глобального db, который ведет себя по-разному в зависимости от количества ошибок, которые вы передаете, давая вам возможность запускать один и тот же тестовый файл разное с разными ожиданиями.

Как запустить один и тот же тест более одного раза

После завершения теста delete require.cache[require.resolve('../test/file')], а затем require('../test/file') снова.

Делайте это столько раз, сколько вам нужно.

При обнаружении условных признаков

Обычно я запускаю тест несколько раз, удаляя глобальные конструкторы, если они исправлены с отступлением. Я также обычно храню их, чтобы потом их можно было вернуть.

Когда код очевиден, но не должен быть достигнут

В случае, если у вас есть if (err) process.exit(1);, вы редко хотите достичь этой части кода. Istanbul понимает различные комментарии, которые помогут вам пропустить некоторые части теста, например /* istanbul ignore if */ или ignore else, или даже общий ignore next.

Пожалуйста, подумайте дважды, если вы просто ленивый, или эту часть действительно можно безопасно пропустить ... Я пару раз укусил из-за плохо обработанной ошибки, что является катастрофой, поскольку когда это происходит, когда вам нужно больше всего вашего кода, чтобы продолжать работать и / или предоставлять вам всю необходимую информацию.

Что покрывается?

Возможно, вы уже знаете это, но файл coverage/lcov-report/index.html, который вы можете открыть сразу в любом браузере, покажет вам все части, которые не охвачены вашими тестами.

...