Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing Client-/Server-Side Tests

How should I structure tests containing a mixture of Selenium code (for setting up the page), and client-side Mocha code (for actually performing the tests on the client-side JS being tested)?

I am testing a client-side javascript library. Unit tests work great with Karma, Mocha, and Grunt. The unit-tests can be run locally, or via SauceLabs. The unit tests are able to test basically everything up to the part where a file is actually submitted. This part requires browser automation, and/or manual interaction, and this is what I'm struggling with.

The library in question is a Javascript file-upload library. It has features like chunking, auto-resuming, and much more. It does not require jQuery, and it works on a variety of browsers (IE7-10, FF, Safari (Mac & iOS), Chrome, Android stock browser). So, there are a lot of cases and exceptions to be covered in these tests.

Basically, I need to use Selenium to set up the page. Since I'm testing a client-side JS file-upload library I need to use Selenium to programmatically submit a file so it can actually be uploaded. Once this file has been submitted (the equivalent of selecting a file from the dialog window that appears when you try to upload a file or files online) then client-side tests can be run to ensure the UI has been drawn properly, the file has been found, etc.

I'm trying to wrap my head around how I can test this properly, and how I can set up my test suite to be extensible for the future, robust, and simple/easy to use.

  • Should I inject JS code to be run client-side with Selenium?

    One idea is to inject the client-side JS code at opportune times with Selenium. Here's some pseudo-code of what I'm thinking:

describe("A Test", function () {

   it("injects some JS", function (done) {
        // Assume `getClientSideScript` loads some .js file from the filesystem,
        // reads its contents, and returns the contents as a string (to be executed).
        browser.safeExecute(getClientSideScript('initialize'), function (err, result) {
            // At this point, the client-side library is initialized on the page.

            // Assume that `uploadFile` will submit a file to the `<input type='file'>`
            // element
            utils.uploadFile('file.jpg', function (file) {

                browser.safeExecute(getClientSideScript('test_file_submission'), function (err, result) {
                    assert.ok(/* something about the result */);
                });

            });

        }); 
   });
});

This, to me, would work, but seems like a giant PITA. I would have to come up with some convention for storing and loading the client-side scripts that are loaded. Also, two different test would have two different injected scripts so we'd have a huge collection of one-time-use scripts chillin' out in our repo. I'm also afraid of going down this road and finding out that it is a bad decision or impossible.

Anyone have any experience with this?

  • Mock server...I'm going to need one.

    I could use Sinon.js to make mock servers client-side, or nock to have a separate server-side mock server. The server is super simple, but I believe I need to able to assert client-side that the response from the server was what was expected.

  • Intercepting client-side test results

    Similar to the above, how would I be able to intercept asserts within the client-side code when using Selenium to automate the browser. For example, let's say I wanted to test a request-response cycle between my library and a mock server and I wanted to verify that if my library sends request A to the server it will expect response A. Selenium can't test that. I need to be able to have asserts captured client-side and outputted through Selenium.

Been bangin' my head on the wall trying to figure out the best method to do this. If anyone has any experience with anything similar, please, chime in!

like image 956
Mark Feltner Avatar asked Sep 10 '13 22:09

Mark Feltner


People also ask

What is client-side and server-side testing?

Client-side a/b testing is best used when you are deploying an internal team of marketers to run experiments without the need for them to touch coding. Server-side a/b testing is best used when the scope of an experiment is bigger, for example, changes need to be made at the product level.

What should be done client-side vs server-side?

Client-side or front-end web developers use their programming talents to create visually appealing websites for users. This means they build homepages, shopping pages, and slideshows. Server-side or back-end developers create, design, and manage server-side code responsible for data exchange.

What is meant by server-side testing?

Server-side testing is a method of A/B testing wherein the variations of a test are rendered directly from the webserver and then premeditatedly sent to the visitors' device.

What testing do you perform when doing testing on a client-side?

Client-Side Test Types We can execute three types of tests: Desktop tests — Client-side tests on the desktop browser. Mobile tests — Client-side tests on mobile devices. Limited resources test — Client-side tests with limited resources of CPU, memory, network, localization, etc.


1 Answers

I wouldn't mix these two types of tests at all. You have several different concerns here. You can still get full test coverage without having to combine tests like you are describing.

  • Client side unit tests (using Karma, Mocha, etc.) validate that the JavaScript code is behaving as expected.
  • Server side unit tests (using JUnit or whatever unit testing framework exists for your back end) validate that the server code is behaving as expected.
  • Integration or end-to-end tests (using Selenium) validate generally validate that multiple components are working together correctly. You can use a mock back-end for these if necessary.

You can create Karma/Mocha unit tests to verify the details of whatever processing may exist for that file upload action. Here, you should be testing edge cases of the individual JavaScript functions underneath the UI.

You can then create a Selenium test to purely test the upload action and expected result of uploading the file. You can verify that the correct elements exist on the page and have the expected properties after the upload. The JavaScript is a black box in this case. You are testing from the user's perspective. This will exercise some of the code you unit tested already, but the point of it is to test the connection between front and back ends.

like image 172
Jay Sheridan Avatar answered Sep 27 '22 20:09

Jay Sheridan