Тестовый дебат с мокко-чай-синоном - PullRequest
0 голосов
/ 20 февраля 2019

Я хочу проверить свою debounce функцию, но то же самое относится и к подчеркиванию или lodash.

Я хочу использовать мокко, chai's assert и, возможно, sinon.

Я подготовил codepen .

Таймеры Синона вызывают у меня головную боль;когда я спрашиваю, чтобы мой debounce запустился первым, я все равно получаю ответ, что debused callback не был вызван, тогда как это было!

Давайте посмотрим код:

// sinon timers
it('should not run debounced function too early', function() { 
  var clock = sinon.useFakeTimers();
  var delay = 100;
  var targetFn = sinon.spy();
  var delayedFn = g3.debounce(targetFn, {delay: delay, fireStart: false, fireLast: true});
  // for lodash:
  //var delayedFn = _.debounce(targetFn, delay, {leading:false, trailing:true});
  delayedFn();
  clock.tick(delay - 1);
  clock.restore(); 
  sinon.assert.notCalled(targetFn); 
});

Ошибочные результаты, которые мы получаем изПодчеркните, когда мы меняем значения, управляющие запускаются первым / последним.Может кто-нибудь предложить альтернативу?исправление?

Я также нашел эту ссылку для тестов, вероятно, в Жасмине.

Я хочу изменить следующий блок на mocha:

it('should only happen once', function(){
    var count = 0;
    runs(function(){
        var fn = underscore.debounce(function(){
            count += 1;
        }, 100);

        fn();
        fn();
        fn();
    });

    waitsFor(function(){
        return count > 0;
    }, 'didnt execute', 200);

    runs(function(){
        expect(count).toBe(1);
    });
});

Возможно ли это?

Я могу видеть только этот тест мокко к успеху:

  it('shouldnt execute immediately', function(){
    var hasHappened = false;

    var fn = g3.debounce(function(){
        hasHappened = true;
    }, {fireFirst: false, fireLast: true, delay: 100});

    chai.assert(hasHappened === false, 'error: callback has called');
    fn();
    chai.assert(hasHappened === false, 'error: callback has called');
  });

Если вы знаете кучу тестов, было бы неплохо, чтобы я мог видеть свои ошибки.

1 Ответ

0 голосов
/ 21 февраля 2019

Я наконец нашел решение для багги таймеров Sinon, поскольку они внутренне перекрывают объект Date, setTimeout(), setInterval() и т. Д.

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

Решение состоит в том, чтобы запустить таймер с ... временем!

/*** file 'g3.debounceTest.js' ***/
describe('g3.debounce', function() {
  it('should not run debounced function with: 1 call at elapsed < delay & fireLast: true', function() { 
    var clock = sinon.useFakeTimers();
    // sinon remedy avoids buggy behavior
    clock.tick(1000);
    //console.log(Date.now());
    var delay = 100;
    var spy = sinon.spy();
    var targetFn = function(){console.log('eventually debounced was called!'); spy()};
    var delayedFn = g3.debounce(targetFn, {delay: delay, fireFirst: false, fireLast: true});
    // for lodash:
    //var delayedFn = _.debounce(targetFn, delay, {leading: false, trailing: true});
    delayedFn();
    clock.tick(delay - 1);
    //console.log(Date.now());
    clock.restore(); 
    sinon.assert.notCalled(spy); 
  });

  it('should run debounced function once with: 1 call at elapsed < delay & fireFirst: true', function() { 
    var clock = sinon.useFakeTimers();
    // sinon remedy avoids buggy behavior
    clock.tick(1000);
    //console.log(Date.now());
    var delay = 100;
    var spy = sinon.spy();
    var targetFn = function(){console.log('eventually debounced was called!'); spy()};
    var delayedFn = g3.debounce(targetFn, {delay: delay, fireFirst: true, fireLast: false});
    // for lodash:
    //var delayedFn = _.debounce(targetFn, delay, {leading: true, trailing: false});
    delayedFn();
    clock.tick(delay - 1);
    //console.log(Date.now());
    clock.restore(); 
    sinon.assert.calledOnce(spy); 
  });

  it('should run debounced function once with: 3 calls at elapsed < delay & fireFirst: true', function() { 
    var clock = sinon.useFakeTimers();
    // sinon remedy avoids buggy behavior
    clock.tick(1000);
    //console.log(Date.now());
    var delay = 100;
    var spy = sinon.spy();
    var targetFn = function(){console.log('eventually debounced was called!'); spy()};
    var delayedFn = g3.debounce(targetFn, {delay: delay, fireFirst: true, fireLast: false});
    // for lodash:
    //var delayedFn = _.debounce(targetFn, delay, {leading: true, trailing: false});
    /* 1 */delayedFn();
    /* after 99ms */
    clock.tick(delay - 1);
    //console.log(Date.now());
    /* 2 */delayedFn();
     /* after 99ms */
    clock.tick(delay - 1);
    //console.log(Date.now());
    /* 3 */delayedFn();
    clock.restore(); 
    sinon.assert.calledOnce(spy); 
  });

  it('should run debounced function once with: 3 calls at elapsed < delay & fireLast: true', function() { 
    var clock = sinon.useFakeTimers();
    // sinon remedy avoids buggy behavior
    clock.tick(1000);
    //console.log(Date.now());
    var delay = 100;
    var spy = sinon.spy();
    var targetFn = function(){console.log('eventually debounced was called!'); spy()};
    var delayedFn = g3.debounce(targetFn, {delay: delay, fireFirst: false, fireLast: true});
    // for lodash:
    //var delayedFn = _.debounce(targetFn, delay, {leading: true, trailing: false});
    /* 1 */delayedFn();
    /* after 99ms */
    clock.tick(delay - 1);
    //console.log(Date.now());
    /* 2 */delayedFn();
     /* after 99ms */
    clock.tick(delay - 1);
    //console.log(Date.now());
    /* 3 */delayedFn();
    /* after 100ms */
    clock.tick(delay);
    clock.restore();
    sinon.assert.calledOnce(spy);
  });
});
/***end file 'g3.debounceTest.js' ***/

Я также ввел spy() внутрь обратного вызова, поскольку хотел посмотреть, что происходит с этим обратным вызовом, и неожиданно заметил, что обратный вызов запускается после того, как мы вызываем clock.restore();, но sinon не имеет способа проверить это и остается полностьюне зная, что происходит после clock.restore();.

Вот почему я заставил написать clock.tick(delay); в последнем случае, чтобы позволить sinon «увидеть», что происходит последний вызов.

И наконец, если у вас будет больше идей для тестирования такого асинхронного кода, я бы с удовольствием их увидел.

...