I am writing some e2e tests using protractor 5. What I am trying to achieve is to execute whole tests which shared setup, and specific setup (for groups of tests).
I got following code:
Base.ts:
beforeAll(() => {
console.log("before all base");
});
beforeEach(()=> {
console.log("before each base");
});
afterEach(() => {
console.log("after each base")
});
afterAll(() => {
console.log("after all base");
});
TestSuite1.ts:
require('./Base');
describe("test suite 1", () => {
beforeAll(() => {
console.log("before all 1");
});
beforeEach(()=> {
console.log("before each 1");
});
afterEach(() => {
console.log("after each 1")
});
afterAll(() => {
console.log("after all 1");
});
it("test 1", () => {
console.log("test 1 1");
});
it("test 2", () => {
console.log("test 1 2");
});
});
TestSuite2.ts:
require('./Base');
describe("test suite 2", () => {
it("test 1", () => {
console.log("test 2 1");
});
it("test 2", () => {
console.log("test 2 2");
});
});
and conf.ts:
var testsTimeout = 3600000;
export let config: Config = {
framework: 'jasmine',
capabilities: {
browserName: 'chrome'
},
specs: ['test/TestSuite1.js', 'test/TestSuite2.js'],
seleniumAddress: 'http://localhost:4444/wd/hub',
noGlobals: true,
allScriptsTimeout: testsTimeout
};
I would like to get following output:
before all base
before each base
before all 1
before each 1
test 1 1
after each 1
before each 1
test 1 2
after each 1
after all 1
after each base
before each base
test 2 1
test 2 2
after each base
after all base
Unfornatelly my before/after all and before/after each are grouped together and prints as follows:
before all base
before all 1
before each base
before each 1
test 1 1
after each 1
after each base
.before each base
before each 1
test 1 2
after each 1
after each base
.after all 1
before each base
test 2 1
after each base
.before each base
test 2 2
after each base
.after all base
Is it possible to get execution flow which I expect?
This is possible, your function will be executed before/after everything in your suite.
Idea is to put beforeAll() afterAll() or beforeEach() afterEach() into protractor's configuration file - into onPrepare() section.
This might look like this:
module.exports.config = {
//somewhere in your config
onPrepare: function () {
beforeEach(function () {
//This will be executed before EVERY 'it' in each specfile
})
beforeAll(function () {
//This will be executed before EVERY 'describe' in each specfile (even before nested describes)
})
}
}
Also check other options in protractor config: onComplete() afterLaunch() - they might better work for you instead jasmine functions
You might want to look on jasmine reporters, in case you need to somehow work with test name, test result, suite result, and might be good alternative to before/after functions . They are pretty easy to create and use, check this:
https://jasmine.github.io/edge/custom_reporter.html
I guess this is how Protractor is designed to work. There was an issue which was raised to track the scenario where a beforeAll() runs before any beforeEach() in parent describe block
Check the complete discussion here.
With the current implementation (if I understand correctly), it only
really makes sense to have a single beforeAll, and this should either
be outside of any describe block, or at the top of the outermost
describe block. i.e. It would make no sense for my 2nd beforeAll to be
located where it is.
Related
I am trying to define my mocha tests in json and then parse them and run my tests. However, I find that I am having difficulty running the tests in the callback functions
function addTwoNumbers(a,b){
return a+b;
}
function testAddNumbers(){
describe("testing the addition of 2 numbers",() => {
it('should return the addition',(done) => {
addTwoNumbers(2,2).should.be.equal(4)
done()
})
})
}
//Obtain all the test jsons
glob(__dirname +'/../**/*.doc.json', {} , (err,fileNames) => {
fileNames.forEach(fileName => {
let file = fs.readFileSync(fileName)
let tests = JSON.parse(file)
tests.forEach(test => {
testAddNumbers()
})
})
})
Which returns:
Backend listening on port 3000
0 passing (1ms)
Moving testAddNumbers() outside the glob block works, so I am not too sure of the problem. Eg:
function addTwoNumbers(a,b){
return a+b;
}
function testAddNumbers(){
describe("testing the addition of 2 numbers",() => {
it('should return the addition',(done) => {
addTwoNumbers(2,2).should.be.equal(4)
done()
})
})
}
//Obtain all the test jsons
glob(__dirname +'/../**/*.doc.json', {} , (err,fileNames) => {
fileNames.forEach(fileName => {
let file = fs.readFileSync(fileName)
let tests = JSON.parse(file)
tests.forEach(test => {
})
})
})
testAddNumbers()
returns
Backend listening on port 3000
testing the addition of 2 numbers
√ should return the addition
1 passing (238ms)
Thanks for the help!
I have fixed it in a way that I find rather disgraceful, but if you can do better do enlighten me
Problem:
Mocha was exiting when it reached the end of the file
Solution:
Loop and wait till file has completed running. This must be done within a mocha test or mocha will blatantly ignore you as if you were its mom
describe('Wait for dynamically added tests to complete', function () {
this.timeout(999999999)
it('Waiting...', function (done) {
completed = (function wait() {
// console.log(completed)
// console.log('boomdiyadah')
if (!completed) {
setTimeout(wait, 1000)
} else {
done()
}
})();
})
})
Probably this could be implemented with promises but my life needs to move forward
I am having problems loading filenames into jest.each asynchronously.
My code:
let files: string[][]
function getFilesWorking() {
files = [["test1"], ["test2"]]
}
async function getFilesAsync() {
files = await Promise.resolve([["test1"], ["test2"]])
}
beforeAll(() => {
console.log("before")
})
describe.only("Name of the group", () => {
getFilesAsync()
test.each(files)("runs", f => {})
})
beforeAll is executed before each test but NOT before initialization of test.each, so I end up with undefined.
How can I load files before using test.each?
You can pass an async callback to beforeAll and await getFilesAsync within it
beforeAll(async () => {
await getFilesAsync();
})
As of Jest 28.1.3 and prior, this is not possible. There is an open issue documenting this behavior.
The best thing you can do for now is put your tests in a regular it() test and do a deep value comparison:
it('tests an array of cases', async () => {
const data = await getSomeAsyncData()
const expectedData = [ ... ]
expect(data).toEqual(expectedData)
})
You can use beforeEach to set up code that will run prior to tests for any given scope, https://jestjs.io/docs/setup-teardown:
beforeEach(() => {
console.log('before every test');
});
describe.only(('Name of the group') => {
beforeEach(() => {
console.log('before tests in this describe block');
})
})
Jest is only going to run the tests in your describe.only block. If you want to use beforeEach in other blocks and run those tests as well, change describe.only to describe.
(Edit: I know this is a year late, I'm just trying to look for a similar problem/solution set and thought I could answer this.)
I am using jest for unit testing in my node express application,please excuse , because i am new to all this
in my abc.test.js
const s3Helper = require('../../../../../lib/s3_helper');
beforeEach(async () => {
s3Helper.uploadBufferToS3 = jest.fn(() => true);
});
describe('test1', () => {
it('test1', async () => {
expect(s3Helper.uploadBufferToS3)
.toHaveBeenCalled();
});
});
describe('test2', () => {
it('test2', async () => {
expect(s3Helper.uploadBufferToS3)
.toHaveBeenCalled();
});
});
so when i run this test file in test1 it returns that test is passed, however in test2 it returns expected >=1 returned 0.
since i am mocking it beforeEach i expect it should return 1 for each describe block
I have simplified the example to be able to explain it well. I have an array which I want to iterate on. For each element of the array I want to execute a test with async/await functions, so I have this code:
const chai = require('chai');
const expect = chai.expect;
describe('Each film', async() => {
await Promise.all([1, 2, 3].map(async(n) => {
await new Promise(resolve => setTimeout(() => resolve(), 1000));
console.log('N:', n);
it('test', async() => {
expect(true).to.be.true;
});
}));
});
Executing this results in the following output:
0 passing (1ms)
N: 1
N: 2
N: 3
However, if I don't use async/await it is executed as I would expect, so it generates three tests that are resolved correctly.
What could be happening here?
UPDATE
I finally discovered that setTimeout can be used to load data asynchronously and then generate tests dinamically. This is the explanation from mocha page:
If you need to perform asynchronous operations before any of your suites are run, you may delay the root suite. Run mocha with the --delay flag. This will attach a special callback function, run(), to the global context:
So I finally wrote the code this way:
const chai = require('chai');
const expect = chai.expect;
setTimeout(async() => {
await Promise.all([1, 2, 3].map(async(n) => {
describe(`Element number ${n}`, () => {
it('test', async() => {
await new Promise(resolve => setTimeout(() => resolve(), 1000));
expect(true).to.be.true;
});
});
}));
run();
}, 500);
which generates the following output:
➜ node_modules/.bin/mocha --delay test.js
Element number 1
✓ test (1005ms)
Element number 2
✓ test (1001ms)
Element number 3
✓ test (1002ms)
3 passing (3s)
Mocha does not support asynchronous describe functions. You can generate tests dynamically, as described here, but that generation must still be synchronous.
Any tests that aren't created synchronously won't be picked up by the runner. Hence the 0 passing line at the top of your output. Mocha has decided there are no tests well before your promise resolves.
This isn't to say testing your stuff is impossible, just that you need to rethink how you're using Mocha to test it. The following, for example, would be similar to loading all of your things up front and making an assertion on each one in various tests:
const chai = require('chai');
const expect = chai.expect;
describe('Each item', () => {
let items;
before(async () => {
items = [];
await Promise.all([1, 2, 3].map(async(n) => {
await new Promise(resolve => setTimeout(() => resolve(), 1000));
items.push(n);
}));
})
it('is a number', () => {
for (item of items) {
expect(item).to.be.a('number');
}
});
it('is an integer', () => {
for (item of items) {
expect(item % 1).to.equal(0)
}
});
it('is between 1 and 3', () => {
for (item of items) {
expect(item).to.be.within(1, 3)
}
});
});
Unfortunately you won't be able to make a fully separate test displaying in your output for each item. If you want this, you may check out another test runner. I don't really have enough experience with others to say whether or not any of them support this. I'd be surprised if they do, though, since it's quite unusual.
We have some simple "is this really working" chai tests of an electron app using spectron and WebdriverIO. The example code we started with is from
https://github.com/jwood803/ElectronSpectronDemo as reported in https://github.com/jwood803/ElectronSpectronDemo/issues/2, the chai-as-promised tests are not catching mismatches, so I thought I would add some additional tests to find out why Chai is not failing tests where the electron app has text that doesn't match the expected unit test text.
Let's start with something really simple, the rest of the code is at https://github.com/drjasonharrison/ElectronSpectronDemo
describe('Test Example', function () {
beforeEach(function (done) {
app.start().then(function() { done(); } );
});
afterEach(function (done) {
app.stop().then(function() { done(); });
});
it('yes == no should fail', function () {
chai.expect("yes").to.equal("no");
});
it('yes == yes should succeed', function () {
chai.expect("yes").to.equal("yes");
});
The first unit test fails, the second succeeds.
And when we put the assertion into a function this still detects the failure:
it('should fail, but succeeds!?', function () {
function fn() {
var yes = 'yes';
yes.should.equal('no');
};
fn();
});
So now into the world of electron, webdriverio, and spectron, the application title is supposed to be "Hello World!", so this should fail, but it passes:
it('tests the page title', function () {
page.getApplicationTitle().should.eventually.equal("NO WAY");
});
Hmm, let's try a more familiar test:
it('should fail, waitUntilWindowLoaded, yes != no', function () {
app.client.waitUntilWindowLoaded().getTitle().then(
function (txt) {
console.log('txt = ' + txt);
var yes = 'yes';
yes.should.equal('no');
}
);
});
Output:
✓ should fail, waitUntilWindowLoaded, yes != no
txt = Hello World!
It succeeds? What? Why? How?
Found it! If you look at https://github.com/webdriverio/webdriverio/blob/master/examples/standalone/webdriverio.with.mocha.and.chai.js
you will see that you need to return the promise from each of the tests. This is typical for async chai/mocha tests:
it('tests the page title', function () {
return page.getApplicationTitle().should.eventually.equal("NO WAY");
});
If you do that, then the chai test is actually correctly evaluated.