qunited 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.gitignore +13 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +9 -0
  4. data/bin/qunited +23 -0
  5. data/lib/qunited/js_runner/base.rb +34 -0
  6. data/lib/qunited/js_runner/rhino/js/env.rhino.js +14006 -0
  7. data/lib/qunited/js_runner/rhino/js/js.jar +0 -0
  8. data/lib/qunited/js_runner/rhino/js/qunit-runner.js +168 -0
  9. data/lib/qunited/js_runner/rhino/js/qunit.js +1838 -0
  10. data/lib/qunited/js_runner/rhino/js/yaml.js +22 -0
  11. data/lib/qunited/js_runner/rhino.rb +65 -0
  12. data/lib/qunited/js_runner.rb +2 -0
  13. data/lib/qunited/rake_task.rb +87 -0
  14. data/lib/qunited/results.rb +164 -0
  15. data/lib/qunited/runner.rb +23 -0
  16. data/lib/qunited/version.rb +3 -0
  17. data/lib/qunited.rb +4 -0
  18. data/qunited.gemspec +20 -0
  19. data/test/fixtures/basic_project/app/assets/javascripts/application.js +6 -0
  20. data/test/fixtures/basic_project/test/javascripts/test_basics.js +6 -0
  21. data/test/fixtures/basic_project/test/javascripts/test_math.js +12 -0
  22. data/test/fixtures/dom_project/app/assets/javascripts/application.js +6 -0
  23. data/test/fixtures/dom_project/test/javascripts/test_misc.js +5 -0
  24. data/test/fixtures/errors_project/app/assets/javascripts/no_error.js +5 -0
  25. data/test/fixtures/errors_project/app/assets/javascripts/syntax_error.js +7 -0
  26. data/test/fixtures/errors_project/app/assets/javascripts/undefined_error.js +9 -0
  27. data/test/fixtures/errors_project/test/javascripts/this_test_has_no_errors_in_it.js +5 -0
  28. data/test/fixtures/errors_project/test/javascripts/this_test_has_no_tests.js +4 -0
  29. data/test/fixtures/errors_project/test/javascripts/this_test_has_syntax_error.js +10 -0
  30. data/test/fixtures/errors_project/test/javascripts/this_test_has_undefined_error.js +10 -0
  31. data/test/fixtures/failures_project/app/assets/javascripts/application.js +5 -0
  32. data/test/fixtures/failures_project/test/javascripts/test_basics.js +11 -0
  33. data/test/fixtures/failures_project/test/javascripts/test_math.js +12 -0
  34. data/test/test_helper.rb +5 -0
  35. data/test/unit/test_results.rb +338 -0
  36. data/test/unit/test_rhino_runner.rb +114 -0
  37. metadata +100 -0
@@ -0,0 +1,168 @@
1
+ // Runs QUnit tests with Envjs and outputs test results as
2
+ // an array of data serialized in YAML format.
3
+ //
4
+ // The first argument should be the lib directory containing JavaScript dependencies. The second
5
+ // argument is the file to use for test results output. The next arguments are source JavaScript
6
+ // files to test, until "--" is encountered. After the "--" the rest of the arguments are QUnit
7
+ // test files.
8
+ //
9
+ // Example:
10
+ // java -jar js.jar -opt -1 qunit-runner.js libdir outfile.yaml source.js -- test1.js test2.js
11
+ // ^ our args start here
12
+
13
+ var QUnited = { sourceFiles: [], testFiles: [] };
14
+
15
+ (function(args) {
16
+ var libDir = args.shift();
17
+ QUnited.outputFile = args.shift();
18
+
19
+ ['env.rhino.js', 'qunit.js', 'yaml.js'].forEach(function(lib) {
20
+ load(libDir + '/' + lib);
21
+ });
22
+
23
+ var readingSource = true;
24
+ args.forEach(function(arg) {
25
+ if (arg === '--') {
26
+ readingSource = false; // Now reading tests
27
+ } else {
28
+ (readingSource ? QUnited.sourceFiles : QUnited.testFiles).push(arg);
29
+ }
30
+ });
31
+
32
+ // QUnit config
33
+ QUnit.init();
34
+ QUnit.config.blocking = false;
35
+ QUnit.config.autorun = true;
36
+ QUnit.config.updateRate = 0;
37
+
38
+ // Various state we'll need while running the tests
39
+ QUnited.modulesMap = {};
40
+ QUnited.currentTestFile = null; // Set when loading files, see below
41
+ var currentModule, currentTest;
42
+
43
+ ///// Listen for QUnit events during tests
44
+
45
+ QUnit.testStart(function(data) {
46
+ currentTest = {
47
+ name: data.name,
48
+ assertion_data: [], // Ruby-style, since we'll be reading it with Ruby
49
+ start: new Date(),
50
+ assertions: 0,
51
+ file: QUnited.currentTestFile
52
+ };
53
+
54
+ var moduleName = data.module || "(no module)",
55
+ module = QUnited.modulesMap[moduleName];
56
+ if (!module) {
57
+ module = {name: moduleName, tests: []};
58
+ QUnited.modulesMap[moduleName] = module;
59
+ }
60
+ module.tests.push(currentTest);
61
+ });
62
+
63
+ QUnit.testDone(function(data) {
64
+ currentTest.duration = ((new Date()).getTime() - currentTest.start.getTime()) / 1000;
65
+ currentTest.failed = data.failed;
66
+ currentTest.total = data.total;
67
+ });
68
+
69
+ /*
70
+ * Called on every assertion AND whenever we have an expect(num) fail. You cannot tell this
71
+ * apart from an assertion (even though you could make a good guess) with certainty so just
72
+ * don't worry about it as it will only throw assertions count off on a failing test.
73
+ */
74
+ QUnit.log(function(data) {
75
+ currentTest.assertions++;
76
+ currentTest.assertion_data.push(data);
77
+ });
78
+
79
+ })(Array.prototype.slice.call(arguments, 0));
80
+
81
+ // Load source files under test
82
+ QUnited.sourceFiles.forEach(function(file) {
83
+ load(file);
84
+ });
85
+
86
+ // Load test files
87
+ QUnited.testFiles.forEach(function(file) {
88
+ QUnited.currentTestFile = file;
89
+
90
+ // There are some tricky issues with loading files in Rhino and properly handling errors in the
91
+ // loaded files (like undefined and syntax errors). Eventually I settled on just loading using
92
+ // Rhino's load() even though it is impossible (in this version, it may be fixed in the future)
93
+ // to know whether or not there was an error in the loaded file. Rhino simply dumps some info to
94
+ // stderr and keeps on going without letting the caller of load() know what happened!
95
+ //
96
+ // Another option is to slurp in the file, eval it, and try/catch the errors and handle them
97
+ // accordingly. But, I found that the slurp and eval approach introduced to many subtle
98
+ // misbehaviors to be worth it.
99
+ //
100
+ // The thing is, if a test file crashes and the tests aren't run then the build will succeed and
101
+ // that is a bad, bad thing. We need to fail the build somehow in this case. A non-ideal solution
102
+ // that I've come up with is to make sure at least one test is run after a file is loaded. A
103
+ // failure when no tests have been written is not unreasonable and it will have the desirable side
104
+ // effect that the build is failed if loading fails and tests are not run.
105
+ load(file);
106
+
107
+ // Check that the file had at least one test in it. See above.
108
+ var foundOne = false;
109
+ Object.keys(QUnited.modulesMap).forEach(function(key) {
110
+ var tests = QUnited.modulesMap[key].tests, i, test;
111
+ for (i = 0; test = tests[i++];) {
112
+ if (test.file === file) {
113
+ foundOne = true;
114
+ break;
115
+ }
116
+ };
117
+ });
118
+
119
+ if (!foundOne) {
120
+ // Create our own test failure in the default module
121
+ var defaultModuleName = "(no module)",
122
+ module = QUnited.modulesMap[defaultModuleName];
123
+ if (!module) {
124
+ module = {name: defaultModuleName, tests: []};
125
+ QUnited.modulesMap[defaultModuleName] = module;
126
+ }
127
+
128
+ // Push our failed test data into the default module
129
+ module.tests.push({
130
+ name: "Nonexistent test",
131
+ assertion_data: [{
132
+ result: false, message: "Test file did not contain any tests (or there was an error loading it)"
133
+ }],
134
+ start: new Date(), duration: 0,
135
+ assertions: 1, failed: 1, total: 1,
136
+ file: file
137
+ });
138
+ }
139
+ });
140
+
141
+ (function() {
142
+ var modules = [];
143
+
144
+ var ISODateString = function(d) {
145
+ function pad(n) { return n < 10 ? '0' + n : n; }
146
+ return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1)+'-' + pad(d.getUTCDate()) + 'T' +
147
+ pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) + 'Z';
148
+ }
149
+
150
+ // Make a modules array for outputing results
151
+ Object.keys(QUnited.modulesMap).forEach(function(key) {
152
+ var mod = QUnited.modulesMap[key],
153
+ tests = mod.tests;
154
+ modules.push(mod);
155
+ tests.forEach(function(test) {
156
+ // YAML serializer doesn't seem to do dates; make them strings
157
+ test.start = ISODateString(test.start);
158
+ // Convert the duration to a string since the YAML serializer makes them all 0s otherwise
159
+ test.duration = "" + test.duration;
160
+ });
161
+ });
162
+
163
+
164
+ // Write all the results as YAML
165
+ var writer = new java.io.PrintWriter(QUnited.outputFile);
166
+ writer.write(YAML.encode(modules));
167
+ writer.close();
168
+ })();