Qunit测试在页面刷新时在通过和失败之间交替

我有两个测试相互引起副作用。 我理解为什么我要替换在第二次测试中内部调用的jQuery内置函数。 然而,我不明白的是为什么测试交替通过和失败。

这个问题很相似但是,我没有直接在qunit-fixture div上做任何事情。

这是我的测试

test('always passing test', function() { // Always passes var panelId = '#PanelMyTab'; var event = {}; var ui = { tab: { name: 'MyTab', }, panel: panelId, }; $('
') .append('Test') .append('Show Form') .appendTo('#qunit-fixture'); jQuery.fn.on = function(event, callback) { ok(this.selector == panelId + ' .export', 'Setting export click event'); equal(callback, tickets.search.getReport, 'Callback being set'); }; loadTab(event, ui); }); test('alternately passing and failing', function() { // Alternates between passing and failing on page refresh expect(5); var testUrl = 'test'; $('
') .append('Get Report') .append('
') .appendTo('#qunit-fixture'); // Setup form mocking $('form.ticketSearch').submit(function() { var urlPattern = new RegExp(testUrl + '$'); ok(urlPattern.test($(this).prop('action')), 'Form action set to link href'); equal($(this).prop('target'), '_blank', 'Open form on a new page'); }); var event = { target: 'a#getReport', }; var result = getReport(event); var form = $('form.ticketSearch'); ok(/notest$/.test($(form).prop('action')), 'Making sure action is not replaced'); equal($(form).prop('target'), '', 'Making sure that target is not replaced'); ok(false === result, 'click event returns false to not refresh page'); });

测试将开始传递,但是当我刷新时,它们将在传递和失败之间交替。

为什么会这样? 即使向url添加GET参数,也会在网页上产生相同的行为。

在失败的情况下,测试失败,因为内部jQuery在设置submit()处理程序时调用.on() 但是为什么在这种情况下测试总是失败? 在页面刷新期间保留状态的浏览器是什么?

更新:

以下是正在测试的代码:

 var tickets = function() { var self = { loadTab: function(event, ui) { $(panel).find('.export').button().on('click', this.getReport); }, search: { getReport: function(event) { var button = event.target; var form = $(button).closest('div.ui-tabs-panel').find('form.ticketSearch').clone(true); $(form).prop('action', $(button).prop('href')); $(form).prop('target', '_blank'); $(form).submit(); return false; } } }; return self; }(); 

我修改了@ Ben的小提琴 ,将你的代码包含在你的两个测试中。 我修改了一些代码以使其正确运行。 当您点击运行按钮时,所有测试都将通过。 再次点击运行按钮时,第二次测试(“交替传递和失败”)将失败 – 这基本上模拟了您的原始问题。

问题是你的第一个测试(“总是通过测试”)通过用重写的jQuery.fn.on函数替换jQuery.fn.on函数来改变全局状态 。 因此,当测试按顺序运行时,第二个测试(“交替传递和失败”)使用不正确的重写jQuery.fn.on函数并失败。 每个unit testing应该将全局状态返回到其测试前状态,以便其他测试可以基于相同的假设运行。

它在pass和fail之间交替的原因是在引擎盖下QUnit总是首先运行失败的测试(它通过cookie或本地存储以某种方式记住它,我不完全确定)。 当它首先运行失败的测试时,第二个测试第一个测试之前运行; 因此,第二个测试得到jQuery的原生function和工作。 当您第三次运行它时,测试将以“原始”顺序运行,第二个测试将使用重写的on函数并失败。

这是工作小提琴 。 我通过缓存原始的var jQueryOn = jQuery.fn.on;在测试后添加修复“un-override” on函数var jQueryOn = jQuery.fn.on; 函数并在测试结束时重置它: jQuery.fn.on = jQueryOn; 。 你可以使用QUnit的模块teardown()方法更好地实现它。

您可以查看https://github.com/jquery/qunit/issues/74了解更多信息。

我不确定如果没有更多信息我可以解决这个问题,但我可以指出一些可能的问题。

第一个测试似乎在第2行上有无效的语法

 var panelId = '#PanelMyTab'); 

但这可能是一种类型的错误,正如你所说,第一次总是过去。

我假设第一个测试传递(并且有效)loadTab(event,ui)必须运行jQuery.fn.on(),没有它没有运行断言。 哪个用jQuery UI Tabs进行一些测试,似乎就是这种情况(只是不确定它是否是你的意图)。

我不确定将这些断言放在该函数中是否可取,并且您必须明白已使用不执行任何操作的函数覆盖了jquery函数,因此可能会导致问题。

你似乎在第二次测试中做了类似的事情,你期待5个断言,但我只能看到最后3个如何运行

 ok(/notest$/.test($(form).prop('action')), 'Making sure action is not replaced'); equal($(form).prop('target'), '', 'Making sure that target is not replaced'); ok(false === result, 'click event returns false to not refresh page'); 

另外2个在提交函数中,看起来不像是作为测试的一部分调用的。

请记住,这些测试是同步的,因此在运行测试和失败之前,它不会等待您点击提交。

这是一个例子

 test('asynchronous test', function() { setTimeout(function() { ok(true); }, 100) }) 

在测试后100ms运行ok会失败。

 test('asynchronous test', function() { // Pause the test first stop(); setTimeout(function() { ok(true); // After the assertion has been called, // continue the test start(); }, 100) }) 

stop()告诉qunit等待和start()去!

这里还有api中详细介绍的asyncTest()

最后,您似乎正在尝试使用这些测试来调试代码。 在firefox中使用chrome开发人员工具或firebug在代码上设置断点并使用console.log()和console.dir()输出信息要容易得多。

话虽如此,我根本不知道它对你有什么用,所以我可能会遗漏一些东西:)如果你仍然卡住了,看看你是否可以添加更多的周围代码以及你想要实现的目标。 希望这可以帮助。

PS:还有一个}; 最后在你给我们的代码中无效,虽然可能与实际应用有关;)