J5tester
J5tester is a stand alone JavaScript unit tester that uses gjs as it's engine. It was developed to test non-DOM JavaScript code such as that produced for use with the GNOME Shell.
Motivations
I use it to test my pure JavaScript AMQP bindings (Kamaloka-js) as it allows me to add automated testing as well as encourages me to start separating out browser specific code from the more generic JavaScript code. I also wanted to scratch an itch and learn the internals of embedding gjs and using it with GObjects.
In the future other engines could be added to both provide cross engine testing as well as facilitate drop in replacements with seed, v8, etc. in the GNOME stack.
Availability and Status
J5tester-0.2 is available but most of the development will happen in git.
Download the tarball: j5tester-0.2.tar.bz2
Git cloning
- anonymous - git://git.gnome.org/j5tester
commit access - ssh://USERNAME@git.gnome.org/git/j5tester
Example
This example shows some features of the J5tester by testing my Kamaloka-js bindings. Feel free to update this with a more GNOME example. For this example we change to the kamaloka-js directory to start running the tests.
kamaloka-js/test/main.js
1 // eval_script is used similar to gjs imports except it works
2 // more like a script tag by evaling the module in the global context
3 //
4 // Note you will need the latest jsio from git
5 eval_script('j5tester_jsio');
6
7 // use the jsio importer to import the module I am testing
8 // as is done when this is run in a browser
9 jsio('import qpid_amqp as amqp');
10
11 // use the gjs importer to import j5tester
12 const J5tester = imports.j5tester;
13
14 print('kamaloka-js unit tests');
15
16 /* convenience function for checking address formats
17 * Params:
18 * t - the test object
19 * name - the address name we expect after it is parsed
20 * subject - the subject string we expect after it is parsed
21 * options - the options we expect after they are parsed
22 */
23 let check_address = function(t, a, name, subject, options) {
24 if(!options)
25 options = {};
26
27 t.indent(); // indent the output
28
29 // check if the name and subject are what we expect, the last param is a optional comment
30 t.assertEquals(a.name, name,"Checking if name is '" + name + "'");
31 t.assertEquals(a.subject, subject, "Checking if subject is '" + subject + "'");
32
33 // print out an info message, we also have t.warn and t.debug
34 t.info("Checking options");
35
36 if(typeof(options) != typeof(a.options))
37 t.fail(typeof(options) + " != " + typeof(a.options)); // you can fail your own checks and print out a custom comment
38
39 if (options) {
40 // check if the options are of type 'object'
41 t.assertTypeOf(a.options, 'object');
42 t.assertEquals(options.length, a.options.length, 'Checking if options has ' + options.length + ' elements');
43
44 for (var o in options) {
45 if (o == 'x-properties') {
46 // TODO: x-properties require more complex checking
47 } else {
48 var test_val = options[o];
49 // check if each option equals what we expect
50 t.assertEquals(test_val, a.options[o], "Checking if option " + o + " == " + test_val);
51 }
52 }
53 }
54
55 // unindent the output
56 t.unindent();
57 }
58
59 let address_tests = {
60 // all object members that start with 'test' are run
61 testValidAddresses: function() {
62 // import our AddressParser class to test
63 jsio('from amqp.protocol import AddressParser');
64
65 var raw_addr = 'test';
66 var a = new AddressParser(raw_addr);
67 this.info("Checking address " + raw_addr);
68 // 'this' is the tester object
69 check_address(this, a, 'test', null, null);
70
71 var raw_addr = 'test2/wow';
72 a = new AddressParser(raw_addr);
73 this.info("Checking address " + raw_addr);
74 check_address(this, a, 'test2', 'wow');
75
76 var raw_addr = 'test3/org.wow;{arg1: 1, "arg2":\'2\'}';
77 a = new AddressParser(raw_addr);
78 this.info("Checking address " + raw_addr);
79 check_address(this, a, 'test3', 'org.wow', {arg1: 1, arg2:'2'});
80
81 var raw_addr = "test4;{\"arg1\": 1, arg2:'2'}";
82 a = new AddressParser(raw_addr);
83 this.info("Checking address " + raw_addr);
84 check_address(this, a, 'test4', null, {arg1:1, arg2:'2'});
85 }
86 }
87
88 // create the tester object and send in the tests we want to run
89 test = new J5tester.Test({"Address Format Tests": address_tests});
90 // run the test
91 test.run();
To run this test we use this on the command line:
../j5tester-0.2/src/j5tester -p src/ -p jsio/ test/main.js
The -p switch tells j5tester to add a directory to the search path. In this case the kamaloka-js sources reside in the src/ directory and the jsio sources reside in the jsio/ directory. The test/ directory is automatically added to the search path.
Jsio should be fixed in git so that it no longer needs a patch to work with j5tester.