Qunit测试在页面刷新时在通过和失败之间交替 [英] Qunit test alternates between pass and fail on page refresh

查看:77
本文介绍了Qunit测试在页面刷新时在通过和失败之间交替的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a two tests that are causing side effects with each other. I understand why as I am replacing a jQuery built-in function that is being called internally in the second test. However what I don't understand is why the test alternately passes and fails.

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

This question is similar However, I am not doing anything directly on the qunit-fixture div.

这是我的测试

test('always passing test', function() { // Always passes
    var panelId = '#PanelMyTab';

    var event = {};
    var ui = {
        tab: {
            name: 'MyTab',
        },
        panel: panelId,
    };

    $('<div id="' + panelId + '">')
        .append('<a href="#" class="export">Test</a>')
        .append('<a href="#" class="showForm">Show Form</a>')
        .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';
    $('<div class="ui-tabs-panel">')
        .append('<a href="'+ testUrl + '" id="getReport">Get Report</a>')
        .append('<form action="notest" target="" class="ticketSearch"></form>')
        .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');
});

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

The tests will start off passing but when I refresh they will alternate between passing and failing.

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

Why is this happening? Even adding GET parameters to the url result in the same behavior on the page.

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

In the failing cases, the test is failing because internal jQuery is calling .on() when the submit() handler is set. But why isn't the test always failing in that case? What is the browser doing that a state is being retained during page refresh?

更新:

以下是正在测试的代码:

Here is the code that is being tested:

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的小提琴,将您的代码包含在两个测试中。我修改了一些代码以使其正确运行。当您点击运行按钮时,所有测试都将通过。再次点击运行按钮时,第二次测试(交替通过和失败)将失败 - 这基本上模拟了您的原始问题。

I've modified @Ben's fiddle to include your code with both of your tests. I modified some of your code to make it run correctly. When you hit the run button all of the tests will pass. When you hit the run button again, the second test ("alternately passing and failing") will fail -- this is basically simulating your original issue.

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

The issue is your first test ("always passing test") alters the global state by replacing the jQuery.fn.on function with an overridden one. Because of this, when the tests are run in order, the second test ("alternately passing and failing") uses the incorrect overridden jQuery.fn.on function and fails. Each unit test should return the global state back to its pre-test state so that other tests can run based on the same assumptions.

为什么它在传递和失败之间交替的原因是在引擎盖下QUnit总是首先运行失败的测试(它通过cookie或本地存储以某种方式记住它,我不完全确定)。当它首先运行失败的测试时,第二个测试在之前运行第一个测试;因此,第二个测试在函数上获得了jQuery的原生并且有效。第三次运行时,测试将以原始顺序运行,第二次测试将使用上的重写并失败。

The reason why it's alternating between pass and fail is that under the hood QUnit always runs failed tests first (it remembers this somehow via cookie or local storage, I'm not exactly sure). When it runs the failed tests first, the second test runs before the first one; as a result, the second test gets jQuery's native on function and works. When you run it a third time, the tests will run in their "original" order and the second test will use the overridden on function and fail.

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

Here's the working fiddle. I've add the fix to "un-override" the on function after the test by caching the original var jQueryOn = jQuery.fn.on; function and resetting it at the end of the test via: jQuery.fn.on = jQueryOn;. You can probably better implement this using QUnit's module teardown() method instead.

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

You can check out https://github.com/jquery/qunit/issues/74 for more info.

这篇关于Qunit测试在页面刷新时在通过和失败之间交替的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆