Angular JS Practical Project Application-Unit Test Framework Design

Keywords: angular npm JSON github

From: http://www.cnblogs.com/vipyoumay/p/5331787.html


In this paper, we introduce the unit and E2E testing of the application developed by angular through the framework of karma and jsmine.

Precondition

  • nodejs
  • webstorm

Create project

Create a blank web project in webstorm

Create html, js folders

Create two folders in the project to store the html and js files used in the project.

Installation framework

Install front-end frame

The front-end framework in the project is mainly angular JS related framework. In order to install the framework conveniently, the bower package manager can be installed.

1) Install the bower package manager

Executing scripts in terminal of webstorm

npm install bower -save

2) Initialize bower.json file

Execution scripts generate bower.json files for managing bower dependencies and configurations.

bower init

3) Installation of frameworks such as angular

In addition to the angular framework to be used in the project, the angular-mocks framework needs to be installed.

bower install bootstrap -save
bower install angular -save
bower install angular-mocks -save

Installation of Server-side Framework

The server relies on nodejs and needs to install the package of nodejs. First, create the package.json file in the root directory.

1) Install http-server module

npm install http-server -save

2) Install other modules

  • jasmine-core:javascript unit testing framework;
  • karma: A tool that simulates javascript scripts in various browsers.
  • karma-chrome-launcher: Tool executed in chrome browser;
  • karma-jasmine: jasmine-core adapter in karma;
  • karma-junit-reporter: Generate JUnit reports;
  • protractor:E2E testing framework

Start the server

To start a node server, you need to configure a script node in package.json, define a dependencies package in dependencies, and configure a start node in script to start the server. The contents of the test node will be explained later.

"name": "angularjs-test",
  "version": "0.0.1",
  "dependencies": {
    "bower": "^1.7.7",
    "http-server": "^0.9.0",
    "jasmine-core": "^2.4.1",
    "karma": "^0.13.22",
    "karma-chrome-launcher": "^0.2.3",
    "karma-jasmine": "^0.3.8",
    "karma-junit-reporter": "^0.4.1",
    "protractor": "^3.2.1"
  },
  "scripts": {
    "postinstall": "bower install",
    "prestart": "npm install",
    "start": "http-server -a localhost -p 8000 -c-1",
    "pretest": "npm install",
    "test": "karma start karma.conf.js",
    "test-single-run": "karma start karma.conf.js  --single-run"
  }

Run the command after configuration, start the server, enter http://localhost:8000 on the browser

npm start

Start unit testing

Write functional code

Create a new JS file index. JS in the file js. In index.js, congroller is defined to implement the simple accumulation method add. The code is as follows:

/**
 * Created by stephen on 2016/3/24.
 */

(function (angular) {
    angular.module('app', []).
    controller('indexCtrl', function ($scope) {
        $scope.add = function (a, b) {
            if(a&&b)
            return Number(a) + Number(b)
            return 0;
        }
    });
})(window.angular);

Create a new HTML file index.html in the file html, add two input boxes for users to get input, and bind the add method in the controller to realize calculator function after input. The code is as follows:

<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
    <meta charset="UTF-8">
    <title>index</title>

</head>
<body>
<div ng-controller="indexCtrl">
    <input type="text" ng-model="a" value="0">
    +
    <input type="text" ng-model="b" value="0">
    =<span id='result'>{{add(a,b)}}</span>
</div>
</body>
</html>
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/bower_components/angular-mocks/angular-mocks.js"></script>
<script src="/js/index.js"></script>

Start the server and see the following effect

Write test code

Create a new file index-test.js in the test folder to write unit tests for index.js.

'use strict';
describe('app', function () {
    beforeEach(module('app'));
    describe('indexCtrl', function () {
        it('add test', inject(function ($controller) {
            var $scope = {};
            //spec body
            var indexCtrl = $controller('indexCtrl', {$scope: $scope});
            expect(indexCtrl).toBeDefined();
            expect($scope.add(2, 3)).toEqual(5);
        }));

    });
});

Unit test configuration

Initialize the karma configuration file to configure karma and execute commands

karma init

In the karma configuration file code, each node has default comments. See

module.exports = function (config) {
    config.set({

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: './',


        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine'],


        // list of files / patterns to load in the browser
        files: [
            'bower_components/angular/angular.min.js',
            'bower_components/angular-mocks/angular-mocks.js',
            'js/index.js',
            'test/index-test.js'
        ],

        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['progress'],


        // web server port
        port: 9876,


        // enable / disable colors in the output (reporters and logs)
        colors: true,


        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,


        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,


        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['Chrome'],


        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: false,

        plugins: [
            'karma-chrome-launcher',
            'karma-jasmine',
            'karma-junit-reporter'
        ],

        junitReporter: {
            outputFile: '/test_out/unit.xml',
            suite: 'unit'
        }
    })
}

Configure test information in package.json scripts and specify the karma file address

"test": "karma start karma.conf.js",

Running unit tests

Run commands, execute tests

npm test

The results are as follows. You can see that the test has passed.

Debugging Unit Testing

In addition to running tests, debugging tests are often required. Click debug on the karma pop-up page and enter the http://localhost:9876/debug.html page to debug the code with the debugging tool provided by chrome:

Unit test coverage

If you need to make statistics on unit test coverage, you can install karma-coverage and configure karma files. After the unit test is completed, the test coverage report document is generated.

npm install karma-coverage -save

Add nodes to the karma.conf.js file

// Added nodes to configure output folders
coverageReporter: {
           type: 'html',
           dir: 'coverage'
       },
// Added node to configure the file address to be tested (here is the controller address)
preprocessors: {'js/*.js': ['coverage']}

// New element'karma-coverage'
plugins: [
          'karma-chrome-launcher',
          'karma-jasmine',
          'karma-junit-reporter',
          'karma-coverage',
      ],
// New element coverage
reporters: ['progress', 'coverage'],

After running the unit test, the coverage folder is generated in the directory, and the test coverage can be viewed by clicking index.html.

E2E test

e2e or end-to-end or UI testing is a test method used to test whether an application's process from beginning to end is the same as the design time. In short, from a user's point of view, it considers that the whole system is a black box, only UI will be exposed to users.

Configuring E2E tests

The new folder e2e-test creates a new protractor.conf.js file to configure the protractor framework. The code is as follows.

exports.config = {

    allScriptsTimeout: 11000,

    baseUrl: 'http://localhost:8000/app/',

    // Capabilities to be passed to the webdriver instance.
    capabilities: {
        'browserName': 'chrome'
    },

    framework: 'jasmine',

    // Spec patterns are relative to the configuration file location passed
    // to protractor (in this example conf.js).
    // They may include glob patterns.
    specs: ['*.js'],

    // Options to be passed to Jasmine-node.
    jasmineNodeOpts: {
        showColors: true, // Use colors in the command line report.
    },

    defaultTimeoutInterval: 30000
};

Configure the package.json scripts script node

"preupdate-webdriver": "npm install",
"update-webdriver": "webdriver-manager update",
"preprotractor": "npm run update-webdriver",
"protractor": "protractor e2e-test/protractor.conf.js"

Write e2e test script

Design test cases: value entry 1 for text box a, value entry 2 for text box b, expected result 3

describe('index.html', function() {

    beforeEach(function() {
        browser.get('http://localhost:8000/html');
    });

    it('get index html', function() {

        var a = element(by.model('a'));
        var b = element(by.model('b'));
        a.sendKeys(1);
        b.sendKeys(2);
        var result = element(by.id('result'));
        expect(result.getText()).toEqual('3');
    });
});

Execute tests to see test results

You need to perform naming to see if you want to update the webdriver. http://sentsin.com/web/658.html),
Manual installation of protractor to global
npm i -g protractor

Note: FQ is required to install or update webdriver. Please set the proxy address in webstrom.
Switch to the Terminal window in webstrom and set up the agent in the Terminal window in the following way:

set PROXY=http://localhost:1080
set HTTP_PROXY=%PROXY%
set HTTPS_PROXY=%PROXY%

After the proxy setup is successful, run the following commands

npm run update-webdriver

Executing e2e test, which will pop up the browser, automatically click on the browser, enter script input to complete the automated e2e test, its essence is to call selenium test.

npm run protractor

Reference material

[1] Official test demo https://github.com/angular/angular-seed

[2] Official documentation of protractor http://angular.github.io/protractor/#/tutorial

[3] Automated E2E testing http://sentsin.com/web/658.html

[4] karma Official Documents https://karma-runner.github.io/latest/intro/configuration.html

[5] Official documentation for angular unit testing https://docs.angularjs.org/guide/unit-testing

Source address https://github.com/stephen-v/angular-e2etest-showcase


=================================================================

The above article is a simple angular unit test. If you use requirejs, angular AMD and other frameworks, it will be more complex to configure. You can refer to this article specifically: https://monkeyissexy.github.io/2016/08/17/karma_jasmine_with_requirejs_angularjs/.

Here I would like to say a few points:
1) The controller uses the ngload asynchronous loading mechanism to load files. Sometimes it makes mistakes when running with karma, because there is no guarantee that the ngload has loaded the files. Let's see that the test case s above all use the $controller method to instantiate the controller so that I can ask the question. So we need to use the method of $injector.instantiate to instantiate. With the method of instantiate, we need to write controller. You can refer to my article about controller. How to write controller? Here's an example.
var ldapCtrlInst = $injector.instantiate(LDAPCtrlDef,{
  					$scope:scope,
  					ldapSrv:ldapSrv,
  					uiGridUtils:{
  						createGridOptions:function(){return {};},
  						resetGridSelection:jasmine.createSpy('resetGridSelection')
  					},
  					modalUtils:{
  						showDlg:function(){
  							var deferred = $q.defer();
  							deferred.resolve("");
  							return deferred.promise;
  						}
  					}
  				});
LDAPCtrlDef in the above code introduces ldap.controller.js into the variables by definition, and then $scope,ldapSrv,uiGridUtils and so on are all parameters that need to be injected into the controller.

2) Because it's a unit test, you don't really need to call the back-end service, so you can simulate it in the following way
var deferred = $q.defer();
deferred.resolve({resultCode:"200",resultObject:[]});
spyOn(ldapSrv,'listLDAP').and.returnValue(deferred.promise);

3) remember to call scope.$digest() in the it method; trigger angular variables to change the binding mechanism

Posted by 87dave87 on Fri, 12 Apr 2019 09:21:31 -0700