Лучший способ проверить.animate с помощью qUnit

Знакомство с TDD я написал простой тестовый костюм для переезда dom элементы слева.

Я тестирую анимации, мне нужно дождаться их завершения. Я не хотел использовать обещания, потому что это похоже на исправление обезьян, и в итоге я использовал пример формы qUnit:

test("move 50", function () {
   //Creates an element for testing and attaches to document
   var el = appendToTest(); 
   ok(el.css('left') == "auto", "element 0");
   stop();
   moveLeft(el, 50, 100);
   setTimeout(function () {
     equal(el.css("left"), "50px");
     start();
  }, 101);//Timeout duration
});

полная скрипка

Тест не пройден на всех версиях jQuery, но 2.x (edge)

failed
Expected:   
"50px"
Result:     
"49.69220733642578px"
Diff:   
"50px" "49.69220733642578px" 

Увеличение длительности тайм-аута делает тест успешным, поэтому я подумал, что анимация не закончилась, пока не было проверено левое свойство.

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

2 ответа

Решение

Вы должны реструктурировать свой тест, а также метод moveLeft, То, что вы в настоящее время делаете, вызывает .animate (Я предполагаю, moveLeft это обертка вокруг .animate) и затем говорит qUnit подождать 101 мс, прежде чем проверять левую позицию элемента. Как вы уже заметили, это не очень надежный способ тестирования!

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

function() {equal(el.css("left"), "50px");start();}

и вы передаете этот обратный вызов .animate в вашем moveLeft функция

например, ваш звонок теперь выглядит так:

//tells qUnit to expect that one assertion will happen.
//this will mean that your test will also fail if moveLeft doesn't invoke the callback.
      expect(1); 
//define the calback function
      var callback = function(){equal(el.css("left"), "50px");start();}
//execute the test:
       moveLeft(el, 50, 100,callback);

скрипка

И в качестве бонуса, теперь у вас есть гораздо более гибкий moveLeft функция, которая может принять любой произвольный обратный вызов. \ О /

На самом деле, есть лучший способ сделать это - использовать поддельные таймеры Синона - http://sinonjs.org/docs/

  1. В настройках инициализируйте фальшивые таймеры:

    setup: function () { this.clock = sinon.useFakeTimers(); }

  2. После звонка moveLeft() в тесте установите поддельный таймер на 100 мс:

    this.clock.tick(100);

  3. Теперь вы можете проверить результат анимации сразу, не используя асинхронный тест:

    equal(el.css("left"), "50px");

Другие вопросы по тегам