Integration/Acceptance testing of a ReactJS App

前端 未结 2 647
清酒与你
清酒与你 2021-02-14 13:27

I\'ve read the documentation about Jest. However this seems to imply unit testing of individual components.

How does one test integration of components, or acceptance t

2条回答
  •  遥遥无期
    2021-02-14 13:53

    The way I solved the problem is to start several processes or services in order to test e2e with mocha:

    1. Webserver: I start a simple webserver (like express) that provides the webpack build packages (https://www.npmjs.com/package/express)
    2. Selenium: for controlling the browser (https://www.npmjs.com/package/selenium-standalone)
    3. mocha within a 'child_process' fork

    This looks in my test_runner.js file following which I start with 'node test_runner.js':

     var async = require('async');
     var web_runner = require('./web_server');'
     //... and other runner scripts
    
     var start = function () {
       console.log('Starting services:');
       async.series([
           function (callback) {
              web_runner.start(args[0], callback);
           },
           function (callback) {
               selenium_runner.start(callback);
           },
           function (callback) {
                mocha_runner.start(args[0], args[1], callback);
           },
           function (callback) {
                selenium_runner.stop(callback_stop, 0);
                mock_runner.stop(callback_stop);
                web_runner.stop(callback_stop);
                callback();
           }
       ]);
    };
    start();
    

    Once the test is done the function stops all services.

    The webserver should be no problem to start. I had some difficilises with the selenium start and found a nice way here: https://github.com/nkbt/nightwatch-autorun/blob/master/index.js

    var selenium = require('selenium-standalone');
    
    function onSeleniumStarted(err, seleniumChild) {
      if (err) {
          process.exit(1);
      }
      process.on('uncaughtException', err2 => {
         console.error(err2.stack);
         seleniumChild.kill('SIGINT');
         process.exit(1);
      });
      startServer(onServerStarted(seleniumChild));
    }
    
    function onSeleniumInstalled(err) {
      if (err) {
         console.error(err.stack);
         process.exit(1);
       }
       selenium.start({seleniumArgs: ['-debug']}, onSeleniumStarted);
    }
    
    selenium.install({}, onSeleniumInstalled);
    

    The mocha is then basically a node process that starts and looks like this in javascript:

    module.exports = {
        start: function (env, test_path, callback) {
            var env_mocha = {env: process.env.ENV = env};
            console.log('Start mocha with:', env_mocha, mocha, test_path);
            cp.fork(mocha,
                [
                    test_path
                ], [
                    env_mocha
                ])
                .on('error', function (error) {
                    runner.stop(error);
                    return process.exit(1);
                })
                .on('close', function (code) {
                    callback();
                });
        },
        stop: function (reason) {
            return process.exit(reason);
        }
    }
    

    Now the test cases have to use a selenium driver. I choose webdriverIO, but there are other alternatives (see here: http://www.slant.co/topics/2814/~node-js-selenium-webdriver-client-libraries-bindings)

    var env = process.env.ENV;
    var webdriverio = require('webdriverio');
    var assert = require('assert');
    
    describe('File: some_test_spec', function () {
    
        var client = {};
    
        before(function (done) {
            client = webdriverio.remote({desiredCapabilities: {browserName: 'chrome'}});
            client.init(done);
        });
    
        after(function (done) {
            client.end(done);
        });
    
        describe('Login success', function () {
                before(function (done) {
                    // user needs to be logged in 
                    client
                        .url(url_start)
                        .waitForVisible('#comp\\.user\\.login\\.button', 1000)
                        .setValue('#comp\\.user\\.login\\.email', 'my@email.com')
                        .setValue('#comp\\.user\\.login\\.password', 'mysecret')
                        .click('#comp\\.user\\.login\\.button')
                        .waitForVisible('#comp\\.user\\.home', 1000)
                        .call(done);
                });
         });
    });
    

    Last note: Phantomjs does not work with the .bind(this) function of react, therefore the Phantomjs Browser is no option at the moment. Reason is explained here: https://groups.google.com/forum/#!msg/phantomjs/r0hPOmnCUpc/uxusqsl2LNoJ

    Hope this helped ;) Good luck.

提交回复
热议问题