Messages

Home Login Logout

Property based testing with QuickCheckJs

We looked at several models and libraries and concluded with QuickCheckJs library which is a property based testing framework. I think it is one of the best candidate.

Recently, I was tasked with investigating a model to test applications automatically with Javascript. We looked at several models and libraries and concluded with QuickCheckJs library which is a property based testing framework. I think it is one of the best candidate.

At first, it was unclear how to get started with the library and implementing a test. However I search and finally find a simple way to use the QC in my own project.

The purpose of this guide is to help one get started in quickly evaluating QC. It purposely leaves out parts of the framework that are not needed to conduct property based testing. Instead, you’ll find out how to quickly write property tests and include them with your favorite testing suite. 

Property vs unit testing

With unit tests, your input and outputs are well defined so you can use them to ensure the HAPY PATH for your functions. We usually use the approach of example-based testing which has the following steps:

  • given a test input I
  • when passed to function under test
  • should return an output O

The unit test completely depends on the person writing the test, and it is non-robust due to unclear requirement undrestandin.

With Property tests, your inputs (and sometimes outputs) are FUZZY, so you can ensure that your functions behave predictably given certain constraints. The main idea of the property based testing is:

for all (x, y, …)
such as precondition(x, y, …) holds
property(x, y, …) is true.

Guide

In this part I show how to load the library into a browser and perform test.

Create a webapp project wit Yeoman and make directory (named libs) in the test folder.

The first thing to do is download and and add the QC library into your project. Open a terminal and run the following command in the libs directory:

wget https://raw.githubusercontent.com/gampleman/quick_check.js/master/dist/jasmine-quick-check.js

The file will be downloaded into the libs directory. The following figure shows folder and files in test folder:

Change the test task in the gulp.js file as follow:

gulp.task('lint:test', () => {
  return lint('test/**/*.js')
    .pipe(gulp.dest('test/spec'));
});

Change the test.js as follow:

(function () {
    'use strict';

    describe('Check QuickCheckJS:', function () {
        describe('The project ', function () {
            it('should contains the qc', function () {
                expect(window.hasOwnProperty('qc')).toBe(true);
            });
        });
    });
})();

finally change the test/index.html as follow:

<!doctype html>
<html>
  <head>
    <title>Jasmine Spec Runner</title>
    <link rel="stylesheet" href="../bower_components/jasmine-core/lib/jasmine-core/jasmine.css">
  </head>
  <body>
    <script src="../bower_components/jasmine-core/lib/jasmine-core/jasmine.js"></script>
    <script src="../bower_components/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
    <script src="../bower_components/jasmine-core/lib/jasmine-core/boot.js"></script>

    <!-- include source files here... -->

    <!-- include spec files here... -->
    <script src="libs/jasmine-quick-check.js"></script>
    <script src="spec/test.js"></script>
  </body>
</html>

To run the test, type the following command in a terminal:

gulp serve:test

The result is:

Now, you are ready to construct tests.

Source code of the example is here(quick-checkjs-example).

Test construction

You can create a test using forAll which takes n args, with the last one being the predicate function the randomly generated arguments are passed to. The test is considered passing when the predicate returns true 100% of the time.

If all return true, the result of checkForAll is true

If any return false, the result of checkForAll is an Object containing additional data about what went wrong.

All tests created using forAll will run 100 times by default. To change it, you have to use a different API which will be covered later.

For example:

expect(property).forAll(generators...)

Working Example

Should you run the following :

(function () {
'use strict';

describe('Give it some context', function () {
describe('maybe a bit more context here', function () {
it('should run here few assertions', function () {
expect(window.hasOwnProperty('qc')).toBe(true);
});
it('should run forAll', function () {
expect(function(i) {
expect(i + i).toBe(2 * i);
}).forAll(qc.int);
});
});
});
})();

You will find the following output:


Let’s see what happens if we assert that subtraction is commutative by adding this function to our suite:

(function () {
    'use strict';

    describe('Give it some context', function () {
        describe('maybe a bit more context here', function () {
            it('should run here few assertions', function () {
                expect(window.hasOwnProperty('qc')).toBe(true);
            });
            it('should run forAll', function () {
                expect(function(i) { 
                    expect(i + i).toBe(2 * i);
                  }).forAll(qc.int);
            });
        });
        describe('find a bug in a sample code', function () {
            it('subtraction is not comutative', function () {
                expect(function(i, j) { 
                    expect(i - j).toBe(j - i);
                }).forAll(qc.int, qc.int);
            });
        });
    });
})();

Running this gives us the following output:

Because subtraction is not commutative, the test fails! The failure gives us an object that tells us that it passed in 0, 1 as arguments, and it was the first test. exc is false because an exception was not thrown. Theoretically, you could assert that a given property test must pass x percent of the time. (Perhaps an async function takes less than 100 ms 90% of the time maybe?)

We’ll explore more about this object later, for now, I think its best to know that failures will return a(truthy)object but they could be used for further inspection and more complex assertions.

Lates posts
Most visited posts

Built with love to give everyone an opportunity to say something to the world
Copyright © 2018 All rights reserved - SITE123 

Terms - Privacy - Abuse

LocalTheme

Help

سوالی دارید؟ با ما مطرح کنید !پشتیبانی آنلاین است.در حال حاضر پشتیبانی غیرفعال است.با تیم ویرا وب صحبت کنیدبا تیم ویرا وب صحبت کنید