Externally determine which test cases fail - Javascript - javascript

I am working on an problem for which i need to detect which test cases fail for any javascript/node.js application, when that application's test suite is run. I need to determine this in a programmatic manner.
Mocha testsuite output result
Consider an example of test output above, for this example I would like to write an external javascript script that can tell me which particular test case failed.
Currently the only solution in my mind is; executing npm test in a javascript child process and read its output from the stdout stream, parse the output and extract necessary information, something like this.
const { spawn } = require('child_process');
const chalk = require('chalk');
const child = spawn('npm.cmd',['test']);
line = 0
child.stdout.on('data', (data) => {
console.log(`${chalk.bgBlue('line = ' + line)} , data = ${data}`);
line++;
});
However, this would be a very strict approach. I would like a more generic way of going about it, that can work for a variety of test modules(not just mocha).
Help would be appreciated !

You can get the state for every test after the execution into the code. So you can know if the test has been passed or not.
The code you need is quite simple. Something like this:
afterEach(function () {
const state = this.currentTest.state;
if (state !== "passed") {
//Do whatever you want with this value
}
});
For example, if you want to store into code, which test has been failed, then you can code this:
var testFailed = []
describe('test', function () {
afterEach(function () {
const state = this.currentTest.state;
if (state !== "passed") {
testFailed.push(this.currentTest.title)
}
});
after(function(){
console.log(testFailed)
})
it('test1', () => {
assert.equal(1, 1)
});
it('test2', () => {
assert.equal(1, 2)
});
})
And the output will be:
test
√ test1
1) test2
[ 'test2' ]
1 passing (15ms)
1 failing
Now you can play with this. You can use the variable to do your work, or even you can create a file or whatever you want to store the info.

Related

Cypress assertion - how to log result (or do extra action) after an assertion

I am writing an test automation feature. I would like to save the test result to my testplan through API.
For example, I would like to be able to achieve something like below
let b = expect(3).eql(4).then((result)=> {
cy.updateTestResult(result, testCaseId)
})
However, there is no '.then()' for what's returned by assertion.
I think I can probably write an if/else, but I think it's kinda of ugly since I need to repeat the logic twice.
Any suggestions are welcome, thank you !!
Maybe you can do something like
....
expect(3).to.eql(4);
// will only get here if the above passes
cy.request('POST', 'http://somehost/some-url', { some: 'json-data-here' }).then(
(response) => {
// ensure you got a 200 back from api call
expect(response.status).to.eq(200);
}
)
To not have to do this manually ever time, you might be able to use afterEach, but I am not sure you will get the info on the test itself or if it passed/failed
#Olore
Update with my final solution here:
...
it('Remove VDC', () => {
cy.delete_vdc_v2(eccData, vdc)
.then(() => {
expect(1).to.equal(2)
testResult = TEST_STATUS.PASS
})
});
});
afterEach('Update Test Result', () => {
cy.updateTestResult(testResult, testRunId, testCaseId, testPointId)
});

How do I get everything covered?

I have a node module I'm trying to write unit tests for. Here's a part of the module:
function _write(level, message) {
if (level <= _current) {
message = message || "No message provided.";
const consoleFn = consoleFunction[level];
const logFn = console[consoleFn];
logFn(`${levelPrefix[level]}: ${message}`);
}
}
When I run the tests including this one:
test('test writing to error log', () => {
logger.__Rewire__('_write', function (level, message) {
console.error(`ERROR: ${message}`);
});
const spy = jest.spyOn(logger, 'error');
logger.error('error message');
expect(spy).toHaveBeenCalledTimes(1);
});
However after running the tests it still looks like the _write function isn't showing up in the coverage results. Is there a way to get jest to understand all the lines of code are getting exercised? Note that "Uncovered Line #s" refers to the exact line numbers of the _write function. I had hoped that by rewiring the function this would make my coverage 100%.
It looks to me like you are mocking the _write function for that test. I don’t expect those lines to get run in this case.
You could write another test that actually uses the _write function.

Testing javascript that updates DOM

I am new to web testing and would like to know how can I test javascript that reads and updates the DOM.
function otherFunction(string) {
// do some processing and return processed data
}
function domUpdater() {
var string = document.getElementById("input").value;
document.getElementById("output").innerHTML = otherFunction(string);
}
I can test easily the otherFunction which accepts and input and returns an output.
expect(otherFunction("input1")).to.be("expected1");
expect(otherFunction("input2")).to.be("expected2");
I am not clear on how can I test the domUpdater function which modifies the DOM?
I usually use jsdom, and in my case since I'm using mocha it would look like this (using jsdom-mocha):
var jsdom = require('mocha-jsdom')
var expect = require('chai').expect
describe('mocha tests', function () {
jsdom()
it('has document', function () {
var div = document.createElement('div')
expect(div.nodeName).eql('DIV')
})
})
However if you can afford it (the tests tend to take a bit longer to run) i would recommend looking into running your tests in a headless browser, using something like Puppeteer.
A quick google search yielded this for how to run jest with puppeteer:
First install jest-puppeteer
yarn add --dev jest-puppeteer
Specify preset in your Jest configuration:
{
"preset": "jest-puppeteer"
}
Write your test
describe('Google', () => {
beforeAll(async () => {
await page.goto('https://google.com');
});
it('should be titled "Google"', async () => {
await expect(page.title()).resolves.toMatch('Google');
});
});

Using asynchronous commands in nightwatch e2e tests

I have a following e2e scenario written using Nightwatch:
var Q = require('q');
module.exports = {
afterEach: function (browser, done) {
browser.end(function() {
done();
});
},
'should display same data on second page as on first page': function (browser) {
//Given
var firstPage = bowser.pages.first()
//When
Q.all([
firstPage.getTextPromise('#element1'),
firstPage.getTextPromise('#element2'),
firstPage.getTextPromise('#element3')]
).then( function(values) {
users.click('#linkToSecondPage');
//Then
var secondPage = browser.page.secondPage();
secondPage.expect.element('#dataElement1').text.to.equal(values[0]).before(5000);
secondPage.expect.element('#dataElemnet2').contains.text(values[1]);
secondPage.expect.element('#dataElement3').contains.text(values[2]);
});
} }
The getTextPromise command is defined by me in following way:
commands: [{
getTextPromise: function(selector) {
var self = this;
return Q.Promise(function (resolve, reject) {
self.getText(selector, function(result) {resolve(result.value); });
});
} }]
The rationale behind this scenarion is to remember some values on one page before clicking on link to second page
and then checking that on second page the same content is displayed (for example, you click on one item in a table
and go to page displaying details of this particular item).
Unfortunately, I observed that this test sometimes does not check things inside the then callback.
I think this is caused by the test finishing (calling done in afterEach()) before he callback returns.
I thought there was a done() callback passed to the test (much like in nightwatch async unit tests) that I could use but apparently there is not.
Is there a proper way to do this in Nightwatch? Perhaps I am using commands in wrong way?
Nightwatch will keep track of command run order itself if the command runs a method on 'this', and returns 'this'.
Try a command like this, adapted as a page command if you prefer:
exports.command = function() {
var self = this;
var globals = self.globals;
if (!globals.values) { globals.values = []; }
var link = 'some_xpath';
self.getText('selector', function(result) {
if(result.status !== -1){
self.globals.values.push = result.value;
}
});
return self;
};
Because the command returns this. It can be chained and you could be sure the commands run in order without manually writing promises.
example:
var firstPage = bowser.pages.first()
var secondPage = browser.page.secondPage();
firstPage.getTextPromise('#element1')
.getTextPromise('#element2')
.getTextPromise('#element3');
secondPage.expect.element('#dataElement1').text.to.equal(global.values[0]).before(5000)
.expect.element('#dataElemnet2').contains.text(global.values[1])
.expect.element('#dataElement3').contains.text(global.values[2]);
I haven't tested this out so it may need a slight tweak. Hopefully it gives a rough idea of how to chain your commands the nightwatch way. If you run into a problem let me know.

Node.js with mocha test

if I have a function as the following:
function foo(request,response){
var val = request.param('data');
//code here
});
how can I create a mocha test function for this to pass the request and response parameters.
The function you wrote above can be seen as a controller - it handles the request and gives back a response.
There are few things you can do:
You can test the route itself - make a http request to the endpoint which uses this controller and test if it behaves correctly - you can use request/supertest/superagent libraries for example.
You can mock the request and response objects and test the code directly - it doesn't require a server to be started, but you need to spend some time to mock out the objects correctly.
It depends on what your "code here" does, and what you want to do :
Test the logic
If you can separate the code in a method that accepts "val", and returns a result, then just test that.
Usually, getting the params from a request, and passing the results to a response is a no-brainer, and not worth testing.
foo : function (req, res) {
// Do you really need to test that ?
var data = req.param("data");
// You probably want to test that
var bar = doFooLogic(data);
// Do you really need to test that ?
res.json(bar);
},
doFooLogic : function (data) {
...
}
And a test like :
describe("foo's logic", function () {
it("does stuff", function () {
// Just test the logic.
// This assumes you exposed the doFooLogic, which is probably acceptable
var bar = doFooLogic(42);
assert(bar.xxxx); // Whatever
});
});
Test the req/response function:
If you really want that, if you're just using "param" on the request object, you might be able to easily mock the request / response (this is JS, you just need to pass something that has the same functions available) :
describe(..., function () {
it("does whatever", function () {
var mockRequest = {
param : function (key) {
if (key === "data") {
return 42;
} else {
throw new Error("UNexpected key", key)
}
}
}
var mockResponse = {
// mock whatever function you need here
json : function (whatever) {
assert(whatever.xxxx) // compare what you put into the response, for example
}
}
// Then do the call
foo (mockRequest, mockResponse);
// The hard part is then how to test the response was passed the right stuff.
// That's why testing the logic is probably easier.
I think you can simply mock it with something like Sinon.js . It should be something like this:
describe('...', function( done ){
it('should test something', function(done){
var mock = sinon.stub(request, "param").withArgs("data").returns("Whatever");
var val = request.param('data');
//do your logic with that value
assert.equal(/*whatever value you want check*/);
mock.restore();
done();
}
}
And you don't have to take care about request's content.

Categories

Resources