Build the Web test environment using Karma + Jasmine
Introduction to the
Now, a dizzying number of Web frameworks are popping up. As browsers evolve, some front-end frameworks try to implement server-side functions and technologies on the browser side, such as MVC frameworks like AngularJS and ExtJS. With the increasing complexity of front-end code and the sudden increase in code volume, how do you ensure that the code is correct? How do I write and run test cases on the Web side? The Jasmine testing framework has certainly eased developers’ concerns.
However, Web development has always had its quirks. For example, pages often need to run on multiple devices (desktop, mobile, handheld, etc.), so how do you test your code on these devices? Karma test platform is designed to provide such a solution.
As a programmer, you not only need to be able to write test cases, you also need to know how to run them. Based on the above questions, this article introduces the two excellent testing frameworks and running platforms.
Introduction of Jasmine
Jasmine Framework introduction
Jasmine is a behavior-driven testing framework for JavaScript development that doesn’t rely on any other JavaScript frameworks or document Object Model (DOM). The latest version has improved support for Node.js, as well as some internal quality improvements.
Figure 1. Jasmine framework
Its main features:
- Does not rely on any other JavaScript framework
- Don’t need the DOM
- Simple structure
- It can be run in Node.js or Html
- Behavior driven development of Jasmine
Project Git repository address
Obtaining the installation package
The latest Jasmine installation package can be downloaded from the open Source community website. The current Standalone version is 2.8.0. Download address
You can also use the NPM command (node.js must be installed first)
npm install –save-dev jasmine
Configure the installation
Decompress the downloaded. Zip file package to the following directory structure:
Figure 2. Directory structure
The directory structure
The lib folder contains Jasmine’s source code. SpecRunner. HTML is a complete example of Jasmine, and you can open SpecRunner. HTML with a browser and see the results of the execution.
The basic concept of Jasmine
Suites & Specs
Suites represent the concept of a test suite, which consists of a number of test cases. Specs are the concrete test cases that comprise them, and each Spec is a test case that tests some function in the application.
- Jasmine uses the global function Describe to describe the Suites of tests. Typically it takes two arguments: a string and a method. The string is the name or title of a particular set of tests (Suite), and the methods are the concrete code that implements the Suite.
- Jasmine uses the global function IT to describe Specs for test cases. Like describe, it has two parameters: a string and a method. Strings are descriptions of a particular test case (Spec), and methods are concrete test code.
Expectations
Jasmine uses a “Expectation” to perform the test results, and each Expectation can be true or false. If all tests in the IT method are true, the test passes. Otherwise, the test fails if any of the assertions are false.
- Expectations are defined by the method Expect, whose parameter is a specific value, known as the actual value. At the same time, a matching method (Matcher) is needed after the Expect method, and the value in the matching method is called the expected value.
Matchers
The result of each Matcher is a Boolean value, which is used to compare the actual value with the expected value. And it’s responsible for informing Jasmine of the implementation of this expectation. Jasmine decides whether the corresponding test case passes or fails. Any Matcher can “decorate” the method with not before calling it, changing the result of the match.
Setup and Teardown
To make setup and teardown code repeatable for each test case, Jasmine provides global beforeEach and afterEach methods. BeforeEach methods are run beforeEach test case execution, while afterEach methods are called afterEach test case execution.
If multiple identical variables are used in a test case, we can define these variables in the global Describe code block, place the initialization code for the variables in the beforeEach method, and reset the values of these variables in the afterEach method.
The describe of nested
Jasmine supports describe nesting. Obviously, at this point, the test set is organized in a tree. Jasmine execution traverses the tree, executing each beforeEach method, it method, and the corresponding afterEach method in order.
Skip the test code block
Suites and Specs can be disabled using the Xdescribe and Xit methods, respectively. At runtime, these Suites and Specs are skipped and do not appear in the results.
Write test cases using Jasmine
Let’s learn how to use these methods to write test cases, starting with a practical requirement.
Before we begin, we need to define the application Model, which defines the scope of the test case as well as the data structure. In other words, these test cases are built around these models.
Listing 1. Mode. Js
function Student(id, name){ this.id = id; this.name = name; this.age = -1; this.teacher = null; } function Teacher(id, name){ this.id = id; this.name = name; this.age = -1; } function SchoolService(){ this.getTeachers = function(){ var teachers = []; for(var i=0; i<5; i++){ var teacher = new Teacher(); teacher.id = "01" + i; teacher.name = "teacher" + i; teachers.push(teacher); } return teachers; } this.getStudents = function(){ var students = []; for(var i=0; i<10; i++){ var student = new Student(); student.id = "00" + i; student.name = "student" + i; var teacher = new Teacher(); var tId = Math.ceil(i/2); teacher.id = "01" + tId; teacher.name = "teacher" + tId; student.teacher = teacher; students.push(student); } return students; } this.getTeacher = function(tId){ var r = null; var teachers = this.getTeachers(); for(var i=0; i<teachers.length; i++){ var teacher = teachers[i]; if(teacher.id == tId){ r = teacher; break; } } return r; } this.getStudent = function(sId){ var r = null; var students = this.getStudents(); for(var i=0; i<students.length; i++){ var student = students[i]; if(student.id == sId){ r = student; break; } } return r; } this.getStudents = function(tId){ var r = []; var students = this.getStudents(); for(var i=0; i<students.length; i++){ var student = students[i]; if(student.teacher && student.teacher.id == tId){ r.push(student); } } return r; }}Copy the code
Here, we define the Teacher and Student classes, as well as the SchoolService class provided externally. It is not hard to see that the SchoolService class is the object we need to focus on testing. Now, let’s write test cases
First, we need to test the getTeachers() method
Listing 2. Test the getTeachers method
describe("A test suite for SchoolService", function() {
var schoolService = new SchoolService();
it("Spec test 1, test the getTeachers function", function() {
var teachers = schoolService.getTeachers();
expect(teachers).not.toBe(null);
expect(teachers.length).toEqual(5);
});
it("Spec test 2: test the getStudents function", function() {
var students = schoolService.getStudents();
expect(students).not.toBe(null);
expect(students.length).toEqual(10);
});
});Copy the code
Next, the more sophisticated Matchers test getTeacher() method is used
Listing 3. Test the getTeacher() method
describe("A test suite for SchoolService", function() {
var schoolService = new SchoolService();
it("Spec test 1, test the getTeachers function", function() {
var teachers = schoolService.getTeachers();
expect(teachers).not.toBe(null);
expect(teachers.length).toEqual(5);
});
it("Spec test 2: test the getStudents function", function() {
var students = schoolService.getStudents();
expect(students).not.toBe(null);
expect(students.length).toEqual(10);
});
it("Spec test 3: test the getTeacher function", function() {
var teacher = schoolService.getTeacher("011");
expect(teacher).not.toBe(null);
expect(teacher.name).toMatch(/teacher/);
expect(teacher.name).toMatch("teacher");
expect(teacher.name).not.toMatch(/people/);
var teacher6 = schoolService.getTeacher("016");
expect(teacher6).toBe(null);
});
});Copy the code
At this point, we find that the teachers and students objects in each method always appear repeatedly. So we considered using the beforeEach/afterEach approach to optimize the test code
Listing 4. Using the beforeEach/afterEach method
describe("A test suite for SchoolService", function() {
var schoolService = new SchoolService();
var teachers = [];
var students = [];
beforeEach(function() {
teachers = schoolService.getTeachers();
students = schoolService.getStudents();
});
it("Spec test 1, test the getTeachers function", function() {
expect(teachers).not.toBe(null);
expect(teachers.length).toEqual(5);
});
it("Spec test 2: test the getStudents function", function() {
expect(students).not.toBe(null);
expect(students.length).toEqual(10);
});
it("Spec test 3: test the getTeacher function", function() {
var teacher = schoolService.getTeacher("011");
expect(teacher).not.toBe(null);
expect(teacher.name).toMatch(/teacher/);
expect(teacher.name).toMatch("teacher");
expect(teacher.name).not.toMatch(/people/);
var teacher6 = schoolService.getTeacher("016");
expect(teacher6).toBe(null);
});
afterEach(function() {
teachers = [];
students = [];
});
});Copy the code
Further, if we could separate the Teacher part of the test case from the Student, the logic of the code would be much cleaner, so we thought of using nested tests
Listing 5. Using nested tests
Describe ("A test suite for SchoolService", function() {// The code above is the same as listing 4 describe("A nested test suite", function() { it("Spec test 4: test the getStudent function", function() { var student10 = schoolService.getStudent("0010"); expect(student10).toBe(null); var student9 = schoolService.getStudent("009"); var teacher = student9.teacher; expect(teacher).toBeDefined(); }); it("Spec test 5: test the getStudentsByTeacher function", function() { var students = schoolService.getStudentsByTeacher("014"); expect(students).not.toBe(null); expect(students.length).toEqual(2); var idArray = []; idArray.push(students[0].id); idArray.push(students[1].id); expect(idArray).toContain("007", "008"); }); }); });Copy the code
Also, once we no longer need to test the Student section, we can simply change Describe to XDescribe. At this point, Jasmine ignores this part of the test code at runtime. (If you want to ignore the IT method, change it to xit)
The advanced use of Jasmine – Spies
Jasmine also provides a few other methods for metadata testing of functions, Timeout testing, asynchronous call testing, and so on. However, these methods are advanced uses of Jasmine, and this article does not attempt to list them all. Instead, he focused on the most characteristic Spies. For other methods, see Jasmine’s official website.
Spy is used to simulate the call of a function and to record the number of times it is called and the parameters passed. Such tests are called metadata tests of functions. For example,
Listing 6. Spies in Jasmine
describe("A test suite for Spies", function() {
var schoolService = new SchoolService();
var teachers = null;
beforeEach(function() {
spyOn(schoolService, "getTeachers");
teachers = schoolService.getTeachers();
});
it("Spec test 1, tracks that the spy was called", function() {
expect(schoolService.getTeachers).toHaveBeenCalledTimes(1);
expect(schoolService.getTeachers).toHaveBeenCalled();
});
it("Spec test 2, tracks that the spy was called x times", function() {
teachers = schoolService.getTeachers();
expect(schoolService.getTeachers).toHaveBeenCalledTimes(2);
});
it("Spec test 3, tracks all the arguments of its calls", function() {
expect(schoolService.getTeachers).toHaveBeenCalledWith() ;
});
it("Spec test4, stops all execution on a function", function() {
expect(teachers).not.toBeDefined();
});
});Copy the code
Listing 7. Simulating the return value using Spies
describe("A test suite for Spies", function() {
var schoolService = new SchoolService();
var teachers = null;
beforeEach(function() {
spyOn(schoolService, "getTeachers").and.returnValue({id: "016", name: "teacher6"});;
teachers = schoolService.getTeachers();
});
it("Spec test 5, when called returns the requested value", function() {
expect(schoolService.getTeachers).toHaveBeenCalledTimes(1);
expect(teachers).toBeDefined();
expect(teachers.id).toEqual("016");
});
});Copy the code
Jasmine is implemented in JavaScript, so it also has to run in a JavaScript environment, and the simplest environment is a Web page. All specs can be run on this page, called Runner.
Listing 8. Running Jasmine
<! DOCTYPE HTML > < HTML > <head> <meta Charset =" UTF-8 "> <title>Jasmine Spec Runner v2.8.0</title> <link rel="shortcut Icon" Type = "image/PNG" href = "lib/jasmine - 2.8.0 / jasmine_favicon. PNG" > < link rel = "stylesheet" Href = "lib/jasmine - 2.8.0 / jasmine. CSS" > < script SRC = "lib/jasmine - 2.8.0 / jasmine. Js" > < / script > < script SRC = "lib/jasmine - 2.8.0 / jasmine - HTML, js" > < / script > < script SRC = "lib/jasmine - 2.8.0 / boot. Js" > < / script > <! -- include source files here... --> <script src="src/model.js"></script> <! -- include spec files here... --> <script src="spec/spec-test.js"></script> </head> <body> </body> </html>Copy the code
The boot.js file is used to initialize the Jasmine environment.
Introduction of Karma
Introduction to the Karma Framework
Karma is a JavaScript Test Runner based on Node.js. The tool can be used to test all major Web browsers, can be integrated into the Continuous Integration (CI) tool, and can be used with other code editors.
Karma monitors each file specified in the configuration file, and whenever the file changes, it sends a signal to the test server to tell all browsers to run the test code again. At this point, the browser reloads the source file and executes the test code. The results are passed back to the server and displayed to the developer in some form.
You can access the browser execution results in the following ways
- Manually using a browser, access the URL http://localhost:9876/
- Automatic – Let Karma start the corresponding browser
Install the Karma
Step 1: Install Node.js
Install the appropriate version of Node.js and ensure that Node Package Manager(NPM) is running properly (by default, NPM is installed with Node.js).
Run the node –version command to check whether Node.js is successfully installed, and run the NPM version command to check whether NPM is running properly.
Step 2: Install Karma
1. Global installation
$NPM install -g karma
Installing Karma goes to the global node_modules directory, so we can run Karma directly from anywhere.
npm install -g karma-cli
This command is used to install karma-cli, which looks for karma executables in the current directory. This allows us to run multiple versions of Karma within one system.
2. Install it locally
Command $NPM install karma –save-dev
$./node_modules/.bin/ Karma if you want to run Karma
Install the plugins
Visit the Plugins section of the Karma website for a wide selection of Karma plugins to install. Here are some commonly used plug-ins
- karma-chrome-launcher
- karma-coverage
- Karma – jasmine
- Karma – firefox – the launcher
- karma-ie-launcher
The Karma of configuration
The basic configuration
The $karma init karmap.conf.js command is used
After executing the command, you are asked a series of questions
- What testing framework do you want to use?
Jasmine, Mocha, and QUnit are all installed by default, so we can just use their names here. If other testing frameworks are used in your application, you need to install their plugins and annotate them in the configuration file (see the plugins in karmap.conf.js).
- Do you want to use Require.js?
Require.js is an implementation of the asynchronous loading specification (AMD). It is used as a base code library for many projects and frameworks, such as Dojo, AngularJs,
- Do you want to capture a browser automatically?
Select the browser that you want to run the test case. Note that the corresponding browser plug-in must be installed successfully.
- What is the location of your source and test files?
Select the directory location where the test case resides. Karma supports wildcard configuration files or directories, such as *. Js, test/**/*.js, etc. If directories or files use relative locations, make it clear that the path is relative to the current directory where the karma command was run.
- Should any of the files included by the previous patterns be excluded?
Files that are not included in the directory.
- Do you want Karma to watch all the files and run tests on change?
Do YOU need Karma to automatically listen for files? And rerun the test case as soon as the file is modified?
The resulting Karma generates the following configuration file (karmap.conf.js) as follows
Listing 10. Karma. Conf. Js
module.exports = function(config) { config.set({ // base path, that will be used to resolve files and exclude basePath: '.. /.. ', frameworks: ['jasmine'], // list of files / patterns to load in the browser files: ['test/client/mocks.js', 'static/karma.src.js', 'test/client/*.spec.js'], // list of files to exclude exclude: [], // use dots reporter, as travis terminal does not support escaping sequences // possible values: 'dots', 'progress' reporters: ['progress', 'junit'], // will be resolved to basePath (in the same way as files/exclude patterns) junitReporter: {outputFile: 'test-results.xml'}, // 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, currently available: // - Chrome, ChromeCanary, Firefox, Opera, Safari (only Mac), PhantomJS, //IE (only Windows) browsers: [process.env.TRAVIS ? 'Firefox' : 'Chrome'], // If browser does not capture in given timeout [ms], kill it captureTimeout: 20000, // Auto run tests on start (when browsers are captured) and exit singleRun: false, // report which specs are slower than 500ms reportSlowerThan: 500, // compile coffee scripts preprocessors: {'**/*.coffee': 'coffee'}, plugins: [ 'karma-jasmine', 'karma-chrome-launcher', 'karma-firefox-launcher', 'karma-junit-reporter' ] }); };Copy the code
Details about configuration items
The purpose of a configuration file is to let Karma know the structure of the project, and a command such as Karma init generates only the basic configuration file. But there are also some configuration items that need to be noted
Karma configuration files can be written in JavaScript, CoffeeScript or TypeScript. If a configuration file is not specified when karma is executed, it finds and loads the configuration file in the following order
- ./karma.conf.js
- ./karma.conf.coffee
- ./karma.conf.ts
- ./.config/karma.conf.js
- ./.config/karma.conf.coffee
- ./.config/karma.conf.ts
Writing configuration files is no different from writing node.js modules.
Listing 11. Karma. Conf. Js
module.exports = function(config) { config.set({ basePath: '.. /.. ', frameworks: ['jasmine'], //... }); };Copy the code
In addition to these basic configurations, f you want to customize the Karma environment to show test coverage and so on, you need to understand the detailed use of some of Karma’s configuration items, such as Preprocessors, Plugins, Browsers, Files.
Files-file entry
Karma uses the Minimatch library to match files. Because minimatch itself is known for its convenience and flexibility, its file expressions are very concise. This expression is used in the following sections of the configuration file
- exclude
- files
- preprocessors
For example,
- **/*.js: files with the suffix “js” in all subdirectories
- / * *! (jquery).js: same meaning as above except “jquery.js” file
- * * / (foo | bar). Js: said in all subdirectories, with “foo js” or “bar. Js” for the name of the file
Detailed configuration items can be found in the file section of the Karma website
Let’s take the files configuration item as an example to understand the specific usage of file matching in detail
files
Use the Files option, which tells Karma which files will be used by the project and which files contain test cases and need to be tested. It is worth noting that the order in which files are configured is the order in which the browser references them.
Match the pattern
- All the relative positions are for basePath.
- BasePath can also be defined using a relative location, where it is relative to the location of the configuration file
- Karma uses the Globa library to solve the problem of file location. It supports the use of minimatch expressions such as test/unit/**/*.spec.js.
Matching order
- The order of patterns determines the order in which files are included in the browser
- If multiple files are matched, the files are sorted alphabetically
- Each file contains one. If multiple patterns match the same file, the file is included in the first matched pattern
The complete example
Listing 12. The files
files: [
// Detailed pattern to include a file. Similarly other options can be used
{
pattern: 'lib/angular.js',
watched: false
},
// Prefer to have watched false for library files. No need to watch them for changes
// simple pattern to load the needed testfiles
// equal to {pattern: 'test/unit/*.spec.js',
//watched: true, served: true, included: true}
'test/unit/*.spec.js',
// this file gets served but will be ignored by the watcher
// note if html2js preprocessor is active, reference as
//`window.__html__['compiled/index.html']`
{
pattern: 'compiled/index.html',
watched: false
},
// this file only gets watched and is otherwise ignored
{
pattern: 'app/index.html',
included: false,
served: false
},
// this file will be served on demand from disk and will be ignored by the watcher
{
pattern: 'compiled/app.js.map',
included: false,
served: true,
watched: false,
nocache:true
}
],Copy the code
For a full explanation, see Karma’s explanation for included, Watched, served
Browsers – Browsers are configured
Capturing browser behavior is always frustrating, and it can take a lot of development time. Using Karma, however, makes this much easier. The reason is that Karma does it automatically for you!
To configure browsers, we just need to set the proper browsers item in the configuration files (e.g. browsers: [‘Chrome’]), Karma and manage these browsers, including starting and closing them.
Karma supported browser
- Chrome and Chrome Canary
- Firefox
- Safari
- PhantomJS
- JSDOM
- Opera
- Internet Explorer
- SauceLabs
- BrowserStack
- many more
Take the Firefox browser as an example. First you need to install the plugin
# Install the launcher first with NPM:
$ npm install karma-firefox-launcher –save-dev
Next, add the new supported browser names to the configuration file
Listing 13. Browsers
module.exports = function(config) {
config.set({
browsers : ['Chrome', 'Firefox']
});
};Copy the code
By default, the Browsers item is unconfigured (that is, its value is blank).
Of course, if you want to test on another device (tablet, phone, etc.), just open the browser on the device and visit http://<hostname>:<port> (default port 9876).
Alternatively, the BROWSER path can be replaced by setting the <BROWSER>_BIN environment variable. For example, change the Firefox browser path in Linux
# Changing the path to the Firefox binary
$ export FIREFOX_BIN=/usr/local/bin/my-firefox-build
For a detailed explanation, please refer to the detailed configuration of browser options on Karma
Preprocessors configuration
Methods defined by Preprocessors are executed before the file is run by the browser (somewhat like aspect-oriented Programming concepts).
Preprocessors can be configured as follows:
Listing 14. Preprocessors
preprocessors: {
'**/*.coffee': ['coffee'],
'**/*.tea': ['coffee'],
'**/*.html': ['html2js']
},Copy the code
Note:
Here, several file expressions are configured with the processor “coffee”. In Karma’s view, the processor’s relationship to an expression is similar to a one-to-many relationship in a database. That is, a processor can be used for multiple file expressions. And most implementations of Preprocessors need to be loaded as plugins.
Some of the most commonly used Preprocessors are as follows
- coffee
- html2js
- coverage
- ng-html2js
- many more
Let’s take the CoffeScript preprocessor example and see how it can be used in configuration files
First we need to install karma-coffee-Preprocessor
# Install it first with NPM
$ npm install karma-coffee-preprocessor –save-dev
Next in the configuration file, we need to do this.
Listing 15. Preprocessors
module.exports = function(config) {
config.set({
preprocessors: {
'**/*.coffee': ['coffee']
}
});
};Copy the code
Some Preprocessors also support configuration, for example
Listing 16. Configuration of Preprocessors
coffeePreprocessor: {
options: {
bare: false
}
}Copy the code
Or you can customize the preprocessor, for example
Listing 17. Configure Preprocessors
customPreprocessors: {
bare_coffee: {
base: 'coffee',
options: {bare: true}
}
}Copy the code
Minimum match minimatch
The key used when configuring Preprocessors is used to filter the files configured in files. (The configuration of files has already been described.)
Let’s take a look at the steps of filtering in detail
- First, expand the file path. All file paths are expanded to absolute paths (depending on the location of basePath).
- Next, match the file path to the configured key value (using the Minimatch library).
With our/my/absolute/path/to/test/unit/file. The path of coffee, for example, if the key value is * * / *. Coffee, matching will be successful, but if the key value is *. Coffee, matching will fail. If the file fails to match, the Preprocessor will not be executed.
Execution order
- If a file matches only one key of the Preprocessors configuration object, Karma executes Preprocessors in the order described in the file. For example,
Listing 18. Order of Minimatch execution
preprocessors: {
'*.js': ['a', 'b']
}Copy the code
At this point, karma will execute “A” and then “B”.
- If a file matches multiple keys, Karma executes Preprocessors in some reasonable order, for example
Listing 19. Order of Minimatch execution
preprocessors: {
'*.js': ['a', 'b'],
'a.*': ['b', 'c']
}Copy the code
For the a.js file, karma will execute ‘a’, then ‘b’, and finally ‘C ‘.
- But if there is a configuration contradiction (perhaps a configuration error) between the two lists, for example:
Listing 20. Minimatch execution order
preprocessors: {
'*.js': ['a', 'b'],
'a.*': ['b', 'a']
}Copy the code
The Karma then randomly selects a configuration order to execute. And such as
Listing 21. Minimatch execution order
preprocessors: {
'*.js': ['a', 'b', 'c'],
'a.*': ['c', 'b', 'd']
}Copy the code
It is certain that ‘a’ will be executed first, ‘d’ last, and that ‘b’ and ‘c’ will be executed in random order.
Start the Karma
The command
$ karma start karma.conf.js
Some configuration attributes can also be overridden as parameters when the karma command is executed, for example
karma start my.conf.js –log-level debug –single-run
At this point, Karma automatically opens the browser and runs the corresponding test case, and the results are printed to the console.
Figure 1. Example picture title
The Karma of the Reporters
By default, Karma displays the results of the test execution on the console. In some cases, we might prefer to use a different output format to display the results. Or let Karma do more things for us, such as showing code coverage, etc., in which case we need Karma’s reporting function.
Karma uses Reporters to display execution results. Let’s take karma-html-reporter as an example
First, we need to download karma-html-Reporter
npm install karma-htmlfile-reporter –save-dev
Alternatively, you can install globally
npm install -g karma-htmlfile-reporter
Next, modify the configuration file
Listing 22. Karma. Conf. Js
module.exports = function(config) { config.set({ ..... . reporters: ['progress', 'html'], htmlReporter: { outputFile: 'test-units.html', // Optional pageTitle: 'Unit Tests', subPageTitle: 'A sample project description', groupSuites: true, useCompactStyle: true, useLegacyStyle: true } }); };Copy the code
Execute the command
Karma start –reporters HTML or karma start karma.conf.js
After the browser runs the test case normally, the test-units.html file is generated in the execution directory. Use a browser to open the test-units.html file
Figure 2. Example picture title
conclusion
Karma is closely associated with AngularJS and further demonstrates its ability as a test run platform. Its excellent architectural design and flexible extensibility have attracted more and more attention from the JavaScript community.
Its features are impressive
- Support for multiple testing frameworks
- Various results Reports are displayed
- Run test cases on multiple browsers
- Support for multiple continuous integration frameworks
- Easy, fast and fun
These features make it different from other testing frameworks and platforms, and it is bound to become one of the indispensable tools for developers.
The resources
- To learn more about how to use Jasmine, visit the Jasmine website.
- To learn more about how to use Karma, visit Karma’s official website.
- Reporters who understand and use Karma can visit here.
- See the article “How to create a Custom Karma Reporter “to learn How to write reporter.