Openui5: Best Practice for QUnit Test page

Created on 12 Aug 2016  路  15Comments  路  Source: SAP/openui5

When writing the unitTests.qunit.html it is unclear to me how to do the QUnit includes and how to write the html structure.
When looking at the guides and sources, I see many different setups:

Is there a best practice setup for QUnit test pages?

Is there an explanation, what the includes files do?

  • sap.ui.thirdparty.qunit: Actual QUnit
  • sap.ui.qunit.qunit-css: QUnit styling
  • sap.ui.qunit.qunit-junit: ???
  • sap.ui.qunit.qunit-coverage: Blanket code coverage
  • sap.ui.qunit.QUnitUtils: ???
  • sap.ui.thirdparty.require: ??? (Found in OpenUI5 code)
documentation fixed

Most helpful comment

Hi,
after a bit of silence i put up a pull request to QUnit.
So we will be able to set autostart: false before loading QUnit. Then we may load it with a regular require statement.

All 15 comments

Hello!

W/o looking at all the other examples, here's one more way to do it: my team has been separating the actual QUnit JavaScript code into a separate *.qunit.js file for years, with very good results. The *.qunit.html file is basically the same every time (just a different title and one different file to include). You can find one example here: ODataMetaModel.qunit.html

What is the advantage of this? Well, you can aggregate tests into s.th. larger, have overall code coverage measured, still select single modules, all w/o the overhead of loading multiple HTML files during a test suite run. You can find one example here: 1Ring.qunit.html

Hope it helps.

Best regards,
Thomas

P.S.: I guess some files are mainly needed for automatic execution and reporting of results.

@ThomasChadzelek Thanks for the reply.

My question is not about writing the actual tests, but about how the html should look like. Specifically the way to include QUnit (<script> vs. require) and the content of the body.

Hi Hirse,

in the docs of QUnit they consistently use the simpliefied html.
So all of our samples should probably use it too.

I actually would recommend the Explored sample if you want to have a good test isolation (all tests will run in the same HTML).

Why require > Script tags - I sometimes changed the nesting of an test.qunit.html site then you need to adjust all script tags. When using require you only need to touch the core stript tag.

Why are the QUnit includes itself done withjQuery.sap.require?
QUnit itself needs to be loaded before dom is ready to be able to set the setting QUnit.config.autostart = false
If you do not set this setting and you did not load all your tests yet QUnit will start and only execute the tests that were loaded before the dom is ready see the QUnit docs of autostart.

sap.ui.require Is not async yet but when it becomes async the tests would be loaded potentially afterDomReady so we wanted our new samples to be written in this way. But acutally we did not go over all the places in the docs and changed this consistently. Therefore i will open an internal issue to cleanup all this and bring more consistency.
tracked internally 1680227206.

For the test requires

  • sap.ui.qunit.qunit-junit: To have a junit report used for CI environments like Jenkins
  • sap.ui.qunit.QUnitUtils: To trigger events on Controls in Javascript (clicking or key events)
  • sap.ui.thirdparty.require: Suprised myself we have require.js in our thirdparty - never seen it used more likely an exotic usecase

The missing requires i tend to use a lot:

  • jQuery.sap.require("sap.ui.thirdparty.sinon"); : Our main library for spying/stubbing and mocking dependencies
  • jQuery.sap.require("sap.ui.thirdparty.sinon-qunit"); Creates sinon sandboxes around unit tests (use with care does not work for async tests)
  • jQuery.sap.require("sap.ui.thirdparty.sinon-ie"); Probably obsolete since we dropped IE9 had to do with fake time problems of sinon i think

Best regards,
Tobias

Thanks for the detailed information, @TobiasOetzel.

I still have questions about the qunit-junit and QUnitUtils files:

  • How would I access the reports?
  • Is the reporter necessary if I just run my tests in a browser / in a grunt task with builtin reporter?
  • What utilities are available in QUnitUtils?
  • Are utils functions comparable to sap.ui.test.actions?

My QUnit.html files currently look like this:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>Unit Tests for my.lib</title>
    <script id="sap-ui-bootstrap"
        src="/sap/ui5/1/resources/sap-ui-core.js"
        data-sap-ui-libs="sap.ui.core, sap.m, my.lib"
        data-sap-ui-theme="sap_bluecrystal"
        data-sap-ui-compatVersion="edge"
        data-sap-ui-preload="async"
        data-sap-ui-resourceroots='{"my.lib": "/my/lib"}'>
    </script>
    <script>
        jQuery.sap.require("sap.ui.thirdparty.qunit");
        jQuery.sap.require("sap.ui.qunit.qunit-css");

        // Filter the code coverage by the tested library
        jQuery.sap.require("sap.ui.qunit.qunit-coverage");
        if (window.blanket) {
            window.blanket.options("sap-ui-cover-only", "my/lib");
        }
        QUnit.config.autostart = false;
        sap.ui.require([
            "my/lib/Control1",
            "my/lib/Control2"
        ], function () {
            QUnit.start();
        });
    </script>
</head>

<body>
    <div id="qunit"></div>
    <div id="qunit-fixture"></div>
</body>

</html>

Do you see anything I could improve?
Is there a way to load all resources with sap.ui.require?

@TobiasOetzel : due to the deprecation of the sync XHR, I would NOT use jQuery.sap.require in a "best practice" template, but use a script tag for QUnit and a link for its CSS.

I understand the drawback of relative URLs, but either you might use (also not without drawbacks) or you don't even have the problem (as in Hirse's use case - he's using server relative paths which don't have to be adjusted when relocating the HTML file).

@Hirse: all files but the qunit.js itself should be loadable via sap.ui.require. But when you load qunit-coverage with sap.ui.require, you won't find the right point in time to configure the includes/excludes. So IMHO it makes sense to load qunit-coverage also via script tag (you then can add the configuration in the script tag, thank's to your pull request :-) ).

There is a test case that was intended as a kind of "Best practice" template for QUnit tests, but it still doesn't reflect all the points from this thread here. I guess we should update it when working on the internal ticket 1680227206.

Hi again,

@codeworrior raised a good point. So probably we should use a script tag for QUnit.
Internally in OpenUI5 and in most of the apps that get developed the URLs are really relative to the html site not to the server.
As pointed out has to be solved in the ticket.

So first your QUnit.html file looks very good to me.
I would probably also require sinon.js because it is so useful for almost every QUnit i write. Sinin can be safely required with sap.ui.require.

  • There is a global variable _$jUnitReport it is saved there. In general jUnit is used in our case to see the test results in Jenkins. I think there is also a different QUnit plugin for generating jUnitReports because our infrastructure is not really public.
  • No it should not be necessary
  • QUnitUtils Contains helper functions we use mainly to test our controls with QUNit you can simulate jQuery events with them. Just noticed that the jsDoc is not generated because it is not flagged as public but functions inside of the file are public so i suppose it should be public.
  • Compared to sap.ui.test.actions: This is a namespace i introduced for OPA to simulate the 2 High level events "Press" equivalent of clicking with the mouse or touching with a finger. And EnterText - typing a string of characters and triggering a change event afterwards. These events are normally not granular enough for testing controls and are typically used with OPA tests.

So quite some work for the ticket piled up

Hi,
after a bit of silence i put up a pull request to QUnit.
So we will be able to set autostart: false before loading QUnit. Then we may load it with a regular require statement.

@TobiasOetzel I highly appreciate your contribution to QUnit, but I guess it will go to jQuery 2.0.x, or? Migrating to 2.0.x will cause a significant effort on our side. I'm not at all against such a migration, it is indeed overdue. I just wanted to raise that point as it might require some joined effort...

Or we have to deviate again from the self-imposed rule that only one version of an OSS should be embedded in sap/ui/thirdparty/.

I wanted to fork our thirdpary folder until we update with the exact same behaviour. If we really want to migrate later on, or use QUnit 2 by altering the require we have the same code running.
I don't know if we will update QUnit 1.x too often. I can also checkout if it can be downported to QUnit 1.x maintanence line.
I just wanted to wait for the forkin if the API I had in mind is ok for the QUnit team.

Update: openui5 code base (all unit tests) have been lifted to QUnit 2.0 syntax now (phew that was some work). Real Migration to QUnit 2.0 is still pending though as we have some hard dependencies to dissolve first

I also created a convenience API "QUnitLoader" based on Tobias change referenced above. When it is merged, we will update our best practices for writing test pages. Until then, our best practices are documented in the "Testing Tutorial" and in the Testing documentation in the developer guide.

Hello @Hirse,

as you saw we meanwhile updated our recommendations for testing several times. With the 1.58 release we have rebuilt the walkthrough step 28+29 and the testing tutorial to show the latest recommendations. Also, the OPA samples and the documentation got renewed, the only source from above that was not updated yet is the internal QUnit unit test, but that should not be of any further relevance.

QUnit: https://openui5nightly.hana.ondemand.com/#/topic/e1ce1de315994a02bf162f4b3b5a9f09
OPA: https://openui5nightly.hana.ondemand.com/#/topic/9bf4dce43b7943d0909cd6c58a933589

In a nutshell these are:

  • Script tags to load the QUnit and helper classes
  • OPA Journeys load their respective page objects
  • Separated HTML file from test run time to enable Karma
  • Small fixes and improvmenets like simplified HTML page setup

In 1.60 which is the next relesse, we will again update our recommendations to new APIs from the UI5 development teams and explain them in our tutorials.

I hope that answered all questions that were left open long time ago.
Let us know if there is anything in addition to clarify

Michael
UI5 Develpment

PS: The QUnitUtils class contains helper functions for working with UI5 and qunit - such as event simulations on controls

Thanks for coming back on this, @Michadelic.

@Michadelic I think we need to update our docs to sinon-4 since it's available under sap/ui/thirdparty/sinon-4 for a while already ;-)

Was this page helpful?
0 / 5 - 0 ratings