Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1c62727
[Feature] Test Load Balancing
Oct 4, 2018
6143f27
1. Create EmberExamTestLoader that extends TestLoader.
Dec 12, 2018
a2be9ea
1. Resolve mixing usage of this and testLoader 
Dec 20, 2018
45fad80
Adding testem-event.js and execution-state-manager.js, handle string …
step2yeung Jan 2, 2019
e6dd86a
EmberExamTestLoader extends either ember-qunit or ember-mocha
step2yeung Jan 3, 2019
03379b9
1. Adding acceptance tests to test load-balance & replay-execution op…
step2yeung Jan 5, 2019
358d4ae
Modify --parallel to accept a number & --load-balance accept a boolean
step2yeung Jan 8, 2019
576f82b
Write test-execution json when browser crashes
step2yeung Jan 8, 2019
ebf87f1
Splitting ember-exam-test-loader for qunit and mocha & moving setupQu…
step2yeung Jan 10, 2019
813fa16
1. Prefix ember-exam error message with `EmberExam:`
Jan 23, 2019
35d3048
Minor fixes
step2yeung Jan 29, 2019
a5dea38
1. Add async-iterator class to simplify async promises and add tests …
Feb 6, 2019
dfa55e8
- Add an inline comment for qunit callbacks
Feb 20, 2019
941a999
- create a dummy testem instance for async-iterator-test in order not…
Feb 22, 2019
aca8646
use window.Testem and check _testem is undefined
step2yeung Feb 26, 2019
6314ca2
Fix exam-test and testem-events-test & Run Prettier on tests & remove…
step2yeung Feb 26, 2019
db0ce01
Removing async await usages
step2yeung Feb 28, 2019
a37566d
Add `--execution-only` option to allow not writing test-execution jso…
Mar 1, 2019
0c1b3a1
1. with `--no-launch` a key, test_page, isn't set in launcher setting…
Mar 1, 2019
df56609
Rename `execution-only` to `no-execution-file` and change conditional…
Mar 6, 2019
560bdf0
1. Fix usage of Map
Mar 7, 2019
5d8364a
Fixes to make --server reruns with replay-execution mode work
step2yeung Mar 7, 2019
b3ba43e
update testem.js timeout to 15s
step2yeung Mar 7, 2019
a9a8581
Adding fixturify to devDependencies
step2yeung Mar 7, 2019
80d343a
Fixes for refreshing browser using `replay-execution` and `no-launch`…
Mar 8, 2019
8141a5d
Remove ember-cli-version-checker and use this.project.pkg to get the …
step2yeung Mar 12, 2019
c691151
1. Throw an error when no-launch is used with load-balance
Mar 12, 2019
fbbe3a5
Prettier, renaming, changes of usage im map
Mar 14, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module.exports = {
'testem.js',
'testem.multiple-test-page.js',
'testem.no-test-page.js',
'testem.simple-test-page.js',
'blueprints/*/index.js',
'config/**/*.js',
'tests/dummy/config/**/*.js',
Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,14 @@ $ ember exam --split=<num> --partition=<num>
The `partition` option allows you to specify which test group to run after using the `split` option. It is one-indexed, so if you specify a split of 3, the last group you could run is 3 as well. You can also run multiple partitions, e.g.:

```bash
$ ember exam --split=4 --partition=1 --partition=2
# comma delimited
$ ember exam --split=4 --partition=1,2

# ranged input
$ ember exam --split=4 --partition=2..4
```

_Note: Ember Exam splits test by modifying the Ember-CLI `TestLoader`, which means that tests are split up according to AMD modules, so it is possible to have unbalanced partitions. For more info, see [issue #60](https://github.com/trentmwillis/ember-exam/issues/60)._
_Note: Ember Exam splits test by modifying the Ember-QUnit's `TestLoader`, which means that tests are split up according to AMD modules, so it is possible to have unbalanced partitions. For more info, see [issue #60](https://github.com/trentmwillis/ember-exam/issues/60)._

<!--```bash
$ ember exam --split=<num> --weighted
Expand Down Expand Up @@ -146,7 +150,7 @@ For example, if you wanted to run your tests across two containers, but have one

```bash
# container 1
ember exam --split=3 --partition=1 --partition=2 --parallel
ember exam --split=3 --partition=1,2 --parallel
```

```bash
Expand Down Expand Up @@ -188,8 +192,8 @@ module.exports = {
If you are working with [Travis CI](https://travis-ci.org/) then you can also easily set up seeded-random runs based on PR numbers. Similar to the following:

```js
var command = [ 'ember', 'exam', '--random' ];
var pr = process.env.TRAVIS_PULL_REQUEST;
const command = [ 'ember', 'exam', '--random' ];
const pr = process.env.TRAVIS_PULL_REQUEST;

if (pr) {
command.push(pr);
Expand Down
141 changes: 141 additions & 0 deletions addon-test-support/-private/async-iterator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
'use strict';

import getUrlParams from './get-url-params';

/**
* A class to iterate a sequencial set of asynchronous events.
*
* @class AsyncIterator
*/
export default class AsyncIterator {
constructor(testem, options) {
this._testem = testem;
this._request = options.request;
this._response = options.response;
this._done = false;
this._current = null;
this._boundHandleResponse = this.handleResponse.bind(this);
this._waiting = false;
// Set a timeout value from either url parameter or default timeout value, 2 s.
this._timeout = getUrlParams().get('asyncTimeout') || 2;
this._browserId = getUrlParams().get('browser');

testem.on(this._response, this._boundHandleResponse);
}

/**
* Return whether the response queue is done.
*/
get done() {
return this._done;
}

toString() {
return `<AsyncIterator (request: ${this._request} response: ${
this._response
})>`;
}

/**
* Handle a response when it's waiting for a response
*
* @param {*} response
*/
handleResponse(response) {
if (this._waiting === false) {
throw new Error(
`${this.toString()} Was not expecting a response, but got a response`
);
} else {
this._waiting = false;
}

try {
if (response.done) {
this.dispose();
}
this._current.resolve(response);
} catch (e) {
this._current.reject(e);
} finally {
this._current = null;

if (this.timer) {
clearTimeout(this.timer);
}
}
}

/**
* Dispose when an iteration is finished.
*
*/
dispose() {
this._done = true;
this._testem.removeEventCallbacks(
this._response,
this._boundHandleResponse
);
}

/**
* Emit the current request.
*
*/
_makeNextRequest() {
this._waiting = true;
this._testem.emit(this._request, this._browserId);
}

/**
* Set a timeout to reject a promise if it doesn't get response within the timeout threshold.
*
* @param {*} reject
*/
_setTimeout(reject) {
clearTimeout(this.timeout);
this.timer = setTimeout(() => {
Comment thread
choheekim marked this conversation as resolved.
if (!this._waiting) {
return;
}
let err = new Error(
`EmberExam: Promise timed out after ${
this._timeout
} s while waiting for response for ${this._request}`
);
reject(err);
}, this._timeout * 1000);
}

/**
* Gets the next response from the request and resolve the promise.
* if it's end of the iteration resolve the promise with done being true.
*
* @return {Promise}
*/
next() {
if (this._done) {
return Promise.resolve({ done: true, value: null });
}
if (this._current) {
return this._current.promise;
}

let resolve, reject;
let promise = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
this._setTimeout(reject);
});

this._current = {
resolve,
reject,
promise
Comment thread
choheekim marked this conversation as resolved.
};

this._makeNextRequest();

return promise;
}
}
69 changes: 69 additions & 0 deletions addon-test-support/-private/ember-exam-mocha-test-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import getUrlParams from './get-url-params';
import splitTestModules from './split-test-modules';
import { TestLoader } from 'ember-mocha/test-loader';

/**
* EmberExamMochaTestLoader extends ember-mocha/test-loader used by `ember test`, since it
* overrides moduleLoadFailure() to log a test failure when a module fails to load
* @class EmberExamMochaTestLoader
* @extends {TestLoader}
*/
export default class EmberExamMochaTestLoader extends TestLoader {
constructor(testem, urlParams) {
super();
this._testModules = [];
this._testem = testem;
this._urlParams = urlParams || getUrlParams();
}

get urlParams() {
return this._urlParams;
}

/**
* Ember-cli-test-loader instantiates a new TestLoader instance and calls loadModules.
* EmberExamMochaTestLoader does not support load() in favor of loadModules().
*/
static load() {
throw new Error('`EmberExamMochaTestLoader` doesn\'t support `load()`.');
}

/**
* require() collects the full list of modules before requiring each module with
* super.require, instead of requiring and unseeing a module when each gets loaded.
*
* @param {string} moduleName
*/
require(moduleName) {
this._testModules.push(moduleName);
}

/**
* Make unsee a no-op to avoid any unwanted resets
*/
unsee() {}
Comment thread
stefanpenner marked this conversation as resolved.

/**
* Loads the test modules depending on the urlParam
*/
loadModules() {
Comment thread
stefanpenner marked this conversation as resolved.
let partitions = this._urlParams.get('partition');
let split = parseInt(this._urlParams.get('split'), 10);

split = isNaN(split) ? 1 : split;

if (partitions === undefined) {
partitions = [1];
} else if (!Array.isArray(partitions)) {
partitions = [partitions];
}

super.loadModules();

this._testModules = splitTestModules(this._testModules, split, partitions);
this._testModules.forEach((moduleName) => {
super.require(moduleName);
super.unsee(moduleName);
});
}
}
Loading