Angular Tutorial: App Testing using Karma
Sukra Trihatmaja | October 11th, 2017
Angular Tutorial: Setting up Unit Testing Using Karma on VS2017
This post is an Angular tutorial for setting up the test environment for an existing Angular application project and running unit tests using Karma on Visual Studio 2017 IDE. Karma is a tool which spawns a web server that executes tests defined by using supported test frameworks for each connected browser. Karma can be used to do testing using most of the common frameworks (including Jasmine, Mocha, QUnit). We use a number of testing tools, but we use Karma in particular because it is easy to configure, simple, and lightweight. It is our preferred task runner for Angular testing because it allows us to run tests on multiple real browsers, watch code changes, automatically re-run the tests, and makes debugging easy.
Other Testing Tools
There are some other tools we use to test Angular applications including Jasmine, Angular Testing Utilities, and Protractor.
Jasmine
Jasmine is an open source testing framework that uses a behavior driven development (BDD) style. In Jasmine tests, you describe what you will test, tell the test what it should do, then check the result against the expected conditions.
Angular Testing Utilities
Angular developers already provide utilities to test Angular applications. TestBed is the most important utility, which allows you to create a module environment for the class you want to test using the configureTestingModule method. For more details about Angular Testing Utilities, you can visit Angular Testing documentation here. In my next post I’ll talk about how to use Angular Testing Utilities.
Protractor
Protractor is a framework built on top of WebDriverJS used for end-to-end testing for Angular and AngularJS applications. Protractor is intended for use in testing applications from the user point-of-view. By default, Protractor uses the Jasmine test framework for its testing interface.
Prerequisites
This tutorial is using a Dashboard Application project as the tested application. This project is built using .NETCore 2.0 Framework, ASP.NET Core 2.0 on the back-end and Angular on the front-end. The project code can be accessed here.
Setting Up the Test Environment
- Install Jasmine
- Install Karma
- Install Karma Plugins
- Since we are going to use typescript, we need to configure jasmine and webpack-env type definitions on tsconfig.json. Add the following configuration on compilerOptions:
- Create a new folder with the name “test” under the ClientApp folder. We will use this folder as the base folder of our testing environment.
- Create configuration file that will let karma-webpack plugin to compile all test cases into one bundle.
- Add karma configuration file (karma.conf.js)
- Create test specification file (test.spec.ts)
> npm install jasmine @types/jasmine ––save-dev
> npm install karma ––save-dev
> npm install karma-jasmine karma-chrome-launcher karma-webpack @types/webpack-env ––save-dev
...
"typeRoots": [
"node_modules/@types"
],
"types": [
"jasmine",
"webpack-env"
]
...
// polyfills
import "core-js";
// zone.js
import "zone.js/dist/zone";
import "zone.js/dist/proxy";
import "zone.js/dist/sync-test";
import "zone.js/dist/async-test";
import "zone.js/dist/fake-async-test";
import "zone.js/dist/jasmine-patch";
import "zone.js/dist/long-stack-trace-zone";
// TestBed initialization
import { TestBed } from "@angular/core/testing";
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from "@angular/platform-browser-dynamic/testing";
TestBed.initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Webpack test context initialization
const context = require.context(".", true, /\.spec\.ts$/);
context.keys().map(context);
// reuse existing webpack.config
// remove entry value since karma-webpack will set its value automatically
var webpackConfig = require("../../webpack.config.js")();
webpackConfig.entry = undefined;
module.exports = (config) => {
config.set({
basePath: ".",
frameworks: ["jasmine"],
files: [
"./test.main.ts"
],
preprocessors: {
"./test.main.ts": ["webpack"]
},
mime: {
"text/x-typescript": ["ts"]
},
webpack: webpackConfig,
webpackMiddleware: {
stats: "error-only"
},
reporters: ["progress"],
port: 9876,
colors: true,
logLevel: config.LOG_ERROR,
singleRun: true,
browsers: ["Chrome"],
concurrency: Infinity
});
}
import { TestBed, ComponentFixture, async } from "@angular/core/testing";
import { NO_ERRORS_SCHEMA, DebugElement } from "@angular/core";
import { By } from "@angular/platform-browser";
import { AppComponent } from "../app/app.component";
describe("AppComponent", () => {
let componentFixture: ComponentFixture;
let debugElement: DebugElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AppComponent],
schemas: [NO_ERRORS_SCHEMA]
});
TestBed.compileComponents();
}));
it("should have 'Dashboard' on header text", () => {
componentFixture = TestBed.createComponent(AppComponent);
debugElement = componentFixture.debugElement;
componentFixture.detectChanges();
const headerElement = debugElement.query(By.css(".page-header h1")).nativeElement;
expect(headerElement.textContent).toContain("Dashboard");
});
});
Running Tests Using NPM Script
- Add “test” script to package.json
- Run the script via command prompt
...
"scripts": {
"build": "webpack",
"test": "karma start ClientApp/test/karma.conf.js"
}
...
> npm test
Running Tests Using Gulp
- Install Gulp
- Add new gulp configuration file (gulpfile.js)
- Configure gulp to start karma task runner (gulp-karma)
- Open Task Runner Explorer window and then run the tests
> npm install gulp ––save-dev
var gulp = require("gulp");
var Server = require("karma").Server;
const configPath = __dirname + "/ClientApp/test/karma.conf.js";
gulp.task("test", function (done) {
new Server({
configFile: configPath,
singleRun: true
}, done).start();
});
gulp.task("tdd", function (done) {
new Server({
configFile: configPath,
singleRun: false
}, done).start();
});
Using karma-spec-reporter
If we use karma progress reporter, we can’t see the description of the test being executed by Karma. We could use karma-spec-reporter plugin to get the Karma report description of our tests. Here are the steps to use the plugin:
- Install karma-spec-reporter plugin
- Update reporter configuration on karma.conf.js
- Re-run the tests
> npm install karma-spec-reporter ––save-dev
...
reporters: ["spec"],
...
Now we have the test environment set. Then we can continue writing the rest of the test codes. Here is the project structure we have right now:
On my next blog post, I will continue this angular tutorial series with Angular Tutorial: Testing using Angular Testing Utilities (TestBed).
The final code of this tutorial can be accessed on my GitHub repository here.
Thanks!