Skip to content

Commit 90c9a0c

Browse files
authored
Merge pull request #72 from gemini-testing/feature/only-implementation
only implementation + silent skip
2 parents a2ff285 + abe5651 commit 90c9a0c

File tree

11 files changed

+307
-65
lines changed

11 files changed

+307
-65
lines changed

README.md

+65-16
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Hermione is the utility for integration testing of web pages using [WebdriverIO]
1919
- [Auto initialization and closing grid sessions](#auto-initialization-and-closing-grid-sessions)
2020
- [Prerequisites](#prerequisites)
2121
- [Skip](#skip)
22+
- [Only](#only)
2223
- [WebdriverIO extensions](#webdriverio-extensions)
2324
- [Sharable meta info](#sharable-meta-info)
2425
- [Execution context](#execution-context)
@@ -82,29 +83,45 @@ hermione --grep login
8283
or simply use `mocha` `only()` API in the test
8384

8485
```
85-
describe.only('user login', () => {...});
86+
describe.only('user login', function() {...});
8687
```
8788

8889
### Skip tests in specific browsers
8990
Sometimes you need to skip test not in all browsers but in a specific one. For example, you don't need to run
9091
some test in ~~ugly~~ IE browsers. In `hermione` you can do it with [hermione helper](#skip). For example,
9192
you can skip some tests in the specific browser
9293
```js
93-
describe('feature', () => {
94+
describe('feature', function() {
9495
hermione.skip.in('ie8', 'it can not work in this browser');
95-
it('nowaday functionality', () => {...});
96+
it('nowaday functionality', function() {...});
9697
});
9798
```
9899

99100
or run tests in one of the browsers
100101
```js
101-
describe('feature', () => {
102+
describe('feature', function() {
102103
// will be skipped in all browsers except chrome
103104
hermione.skip.notIn('chrome', 'it should work only in Chrome');
104-
it('specific functionality', () => {...});
105+
it('specific functionality', function() {...});
105106
});
106107
```
107108

109+
In these cases you will see messages with a skip reason in reports.
110+
111+
To skip suite or test silently (without any messages in reports), you can pass the third argument with silent flag:
112+
```js
113+
hermione.skip.in('ie8', 'skipReason', {silent: true});
114+
// or
115+
hermione.skip.notIn('chrome', 'skipReason', {silent: true});
116+
```
117+
118+
Or you can use another hermione helper - [only](#only), which is silent by default:
119+
```js
120+
hermione.only.in('chrome');
121+
```
122+
123+
It will run tests only in one browser and skip rest silently.
124+
108125
### Flexible tests configuration
109126
`Hermione` has possibility to configure running some set of tests in specific browsers. For example,
110127
```js
@@ -138,32 +155,39 @@ selenium-standalone start
138155
This feature allows you to ignore the specified suite or test in any browser with additional comment.
139156
You can do it by using global `hermione.skip` helper. It supports the following methods:
140157

141-
- `.in` — adds matchers for browsers with additional comment
158+
- `.in` — adds matchers for browsers with additional comment;
142159
- `.notIn``.in` method with reverted value;
143160

144-
Each method takes following arguments:
145-
- browser {String|RegExp|Array<String|RegExp>} — matcher for browser(s) to skip
161+
Each of these methods takes following arguments:
162+
- browser {String|RegExp|Array<String|RegExp>} — matcher for browser(s) to skip;
146163
- [comment] {String} — comment for skipped test;
164+
- [options] {Object} - additional options;
147165

148166
**Note that matchers will be compared with `browserId` specified in a config file, e.g. `chrome-desktop`.**
149167

150168
For example,
151169
```js
152-
describe('feature', () => {
170+
describe('feature', function() {
153171
hermione.skip.in('chrome', "It shouldn't work this way in Chrome");
154-
it('should work this way', () => runTestThisWay());
172+
it('should work this way', function() {
173+
return runTestThisWay();
174+
});
155175

156-
it('should work that way', () => runTestThatWay());
176+
it('should work that way', function() {
177+
return runTestThatWay();
178+
});
157179

158180
hermione.skip.in(['chrome', 'firefox', /ie\d*/], 'Unstable test, see ticket TEST-487');
159-
it('should done some tricky things', () => runTrickyTest());
181+
it('should done some tricky things', function() {
182+
return runTrickyTest();
183+
});
160184
});
161185
```
162186

163187
in this case behaviour `it should work this way` will be skipped only in `chrome` browser, but will be run in other browsers. `It should work that way` will not be ignored. So skip will be applied only to the nearest test. If you need to skip all tests within a suite you can apply `skip` helper to a `describe` - all tests within this suite will be skipped with the same comment.
164188
```js
165189
hermione.skip.in('chrome', 'skip comment');
166-
describe('some feature', () => {
190+
describe('some feature', function() {
167191
it(...);
168192
it(...);
169193
});
@@ -173,24 +197,49 @@ Also you can use `.notIn` method to invert matching. For example,
173197
```js
174198
// ...
175199
hermione.skip.notIn('chrome', 'some comment');
176-
it('should work this way', () => doSomething());
200+
it('should work this way', function() {
201+
return doSomething();
202+
});
177203
// ...
178204
```
179205

180206
in this case test will be skipped in all browsers except `chrome`.
181207

182-
Methods `in` and `notIn` are chainable. So you can skip test in several browsers with different comments. For example,
208+
All of these methods are chainable. So you can skip test in several browsers with different comments. For example,
183209
```js
184210
// ...
185211
hermione.skip
186212
.in('chrome', 'some comment')
187213
.notIn('ie9', 'another comment');
188-
it('test1', () => doSomething());
214+
it('test1', function() {
215+
return doSomething();
216+
});
189217
// ...
190218
```
191219

192220
If you need to skip test in all browsers without a comment you can use [mocha `.skip` method](http://mochajs.org/#inclusive-tests) instead of `hermione.skip.in(/.*/);`. The result will be the same.
193221

222+
## Only
223+
This feature allows you to ignore the specified suite or test in any browser silently (without any messages in reports).
224+
You can do it by using global `hermione.only` helper. It supports only one method:
225+
226+
- `.in``hermione.skip.notIn` method with silent flag
227+
228+
This method takes following arguments:
229+
- browser {String|RegExp|Array<String|RegExp>} — matcher for browser(s) to skip;
230+
231+
For example:
232+
```js
233+
// ...
234+
hermione.only.in('chrome');
235+
it('should work this way', function() {
236+
return doSomething();
237+
});
238+
// ...
239+
```
240+
241+
in this case test will be skipped in all browsers **silently** except `chrome`.
242+
194243
## WebdriverIO extensions
195244
`Hermione` adds some usefull methods and properties to the `webdriverio` session after its initialization.
196245

lib/runner/mocha-runner/mocha-adapter.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const ProxyReporter = require('./proxy-reporter');
44
const logger = require('../../utils').logger;
55
const Skip = require('./skip/');
66
const SkipBuilder = require('./skip/skip-builder');
7+
const OnlyBuilder = require('./skip/only-builder');
78
const Mocha = require('mocha');
89
const path = require('path');
910
const clearRequire = require('clear-require');
@@ -94,10 +95,15 @@ module.exports = class MochaAdapter {
9495
const skip = new Skip();
9596

9697
this.suite.on('pre-require', () => {
98+
const skipBuilder = new SkipBuilder(skip, this._browserAgent.browserId);
99+
const onlyBuilder = new OnlyBuilder(skipBuilder);
100+
97101
global.hermione = {
98-
skip: new SkipBuilder(skip, this._browserAgent.browserId)
102+
skip: skipBuilder,
103+
only: onlyBuilder
99104
};
100105
});
106+
101107
this.suite.on('post-require', () => delete global.hermione);
102108

103109
this._addEventHandler(['suite', 'test'], (runnable) => skip.handleEntity(runnable));

lib/runner/mocha-runner/skip/index.js

+14
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,33 @@ const _ = require('lodash');
55
module.exports = class Skip {
66
constructor() {
77
this.shouldSkip = false;
8+
this.silent = false;
89
}
910

1011
handleEntity(entity) {
1112
if (!this.shouldSkip) {
1213
return;
1314
}
1415

16+
if (this.silent) {
17+
this._rmFromTree(entity);
18+
return;
19+
}
20+
1521
_.extend(entity, {pending: true, skipReason: this.comment});
22+
1623
this._resetInfo();
1724
}
1825

26+
_rmFromTree(entity) {
27+
entity.type === 'test'
28+
? entity.parent.tests.pop()
29+
: entity.parent.suites.pop();
30+
}
31+
1932
_resetInfo() {
2033
this.shouldSkip = false;
34+
this.silent = false;
2135
this.comment = '';
2236
}
2337
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
3+
module.exports = class OnlyBuilder {
4+
constructor(skipBuilder) {
5+
this._skipBuilder = skipBuilder;
6+
}
7+
8+
in(matcher) {
9+
return this._skipBuilder.notIn(matcher, '', {silent: true});
10+
}
11+
};

lib/runner/mocha-runner/skip/skip-builder.js

+13-5
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,28 @@ module.exports = class SkipBuilder {
1717
this._currentBrowserId = browserId;
1818
}
1919

20-
in(matcher, comment) {
21-
return this._processSkip(matcher, comment);
20+
in(matcher, comment, opts) {
21+
return this._processSkip(matcher, comment, opts);
2222
}
2323

24-
notIn(matcher, comment) {
25-
return this._processSkip(matcher, comment, {negate: true});
24+
notIn(matcher, comment, opts) {
25+
opts = _.extend(opts || {}, {negate: true});
26+
return this._processSkip(matcher, comment, opts);
2627
}
2728

2829
_processSkip(matcher, comment, opts) {
29-
const skipFunc = (opts || {}).negate ? _.negate(shouldBeSkipped) : shouldBeSkipped;
30+
opts = _.defaults(opts || {}, {
31+
negate: false,
32+
silent: false
33+
});
34+
35+
const skipFunc = opts.negate ? _.negate(shouldBeSkipped) : shouldBeSkipped;
3036
const shouldSkip = skipFunc(this._currentBrowserId, matcher);
3137
this._skip.shouldSkip = shouldSkip || this._skip.shouldSkip;
38+
3239
if (shouldSkip) {
3340
this._skip.comment = comment;
41+
this._skip.silent = opts.silent === true;
3442
}
3543

3644
return this;

lib/runner/test-skipper.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ module.exports = class TestSkipper {
2121
constructor(config) {
2222
this._skipBrowsers = TestSkipper._getBrowsersToSkip();
2323

24-
TestSkipper._validateUnknownBrowsers(this._skipBrowsers, this._getBtowsersFromConfig(config));
24+
TestSkipper._validateUnknownBrowsers(this._skipBrowsers, this._getBrowsersFromConfig(config));
2525
}
2626

2727
applySkip(suite, browserId) {
@@ -35,7 +35,7 @@ module.exports = class TestSkipper {
3535
return _.contains(this._skipBrowsers, browserId);
3636
}
3737

38-
_getBtowsersFromConfig(config) {
38+
_getBrowsersFromConfig(config) {
3939
return _.keys(config.browsers);
4040
}
4141
};

test/lib/reporter/flat.js

+38-37
Original file line numberDiff line numberDiff line change
@@ -144,60 +144,61 @@ describe('Flat reporter', () => {
144144
assert.equal(result, 'suite test [chrome:test_session] - 100500ms');
145145
});
146146

147-
it('should add skip comment if test was skipped', () => {
148-
test = mkTestStub_({
149-
pending: true,
150-
skipReason: 'some comment'
151-
});
152-
153-
emit(RunnerEvents.TEST_PENDING, test);
147+
describe('skipped tests report', () => {
148+
it('should add skip comment if test was skipped', () => {
149+
test = mkTestStub_({
150+
pending: true,
151+
skipReason: 'some comment'
152+
});
154153

155-
const result = getDeserealizedResult(logger.log.firstCall.args[0]);
154+
emit(RunnerEvents.TEST_PENDING, test);
156155

157-
assert.equal(result, 'suite test [chrome] - 100500ms reason: some comment');
158-
});
156+
const result = getDeserealizedResult(logger.log.firstCall.args[0]);
159157

160-
it('should use parent skip comment if all describe was skipped', () => {
161-
test = mkTestStub_({
162-
pending: true,
163-
skipReason: 'test comment',
164-
parent: {
165-
skipReason: 'suite comment'
166-
}
158+
assert.match(result, /reason: some comment/);
167159
});
168160

169-
emit(RunnerEvents.TEST_PENDING, test);
161+
it('should use parent skip comment if all describe was skipped', () => {
162+
test = mkTestStub_({
163+
pending: true,
164+
skipReason: 'test comment',
165+
parent: {
166+
skipReason: 'suite comment'
167+
}
168+
});
170169

171-
const result = getDeserealizedResult(logger.log.firstCall.args[0]);
170+
emit(RunnerEvents.TEST_PENDING, test);
172171

173-
assert.match(result, /reason: suite comment/);
174-
});
172+
const result = getDeserealizedResult(logger.log.firstCall.args[0]);
175173

176-
it('should use test skip comment if describe was skipped without comment', () => {
177-
test = mkTestStub_({
178-
pending: true,
179-
skipReason: 'test comment',
180-
parent: {some: 'data'}
174+
assert.match(result, /reason: suite comment/);
181175
});
182176

183-
emit(RunnerEvents.TEST_PENDING, test);
177+
it('should use test skip comment if describe was skipped without comment', () => {
178+
test = mkTestStub_({
179+
pending: true,
180+
skipReason: 'test comment',
181+
parent: {some: 'data'}
182+
});
184183

185-
const result = getDeserealizedResult(logger.log.firstCall.args[0]);
184+
emit(RunnerEvents.TEST_PENDING, test);
186185

187-
assert.equal(result, 'suite test [chrome] - 100500ms reason: test comment');
188-
assert.match(result, /reason: test comment/);
189-
});
186+
const result = getDeserealizedResult(logger.log.firstCall.args[0]);
190187

191-
it('should use default message if test was skipped without comment', () => {
192-
test = mkTestStub_({
193-
pending: true
188+
assert.match(result, /reason: test comment/);
194189
});
195190

196-
emit(RunnerEvents.TEST_PENDING, test);
191+
it('should use default message if test was skipped without comment', () => {
192+
test = mkTestStub_({
193+
pending: true
194+
});
197195

198-
const result = getDeserealizedResult(logger.log.firstCall.args[0]);
196+
emit(RunnerEvents.TEST_PENDING, test);
199197

200-
assert.match(result, /reason: no comment/);
198+
const result = getDeserealizedResult(logger.log.firstCall.args[0]);
199+
200+
assert.match(result, /reason: no comment/);
201+
});
201202
});
202203

203204
describe('failed tests report', () => {

0 commit comments

Comments
 (0)