I am new mocha and I need to run one test 100 times. In the following code, a function regexTest is tested for true.
var assert = require('assert');
describe('regexTest',function() {
it('should return true if the string starts with a number',function() {
var i = 1;
while(i++ <= 100) {
assert.equal(true,regexTest(Math.random().toString(36).substring(7)));
}
});
})
function regexTest(randStr) {
let match = randStr.match(/^\d+/);
if(match && match.length > 0) {
return true;
}else{
return false;
}
}
I am not sure if this is the correct way to run a repeated test, inside a while loop. Also, I doubt the results because no matter what, it always returns passed for a single test.
What could be a better approach here?
So first off , your code seems correct and running it locally returns:
~/P/test ➤ node_modules/.bin/mocha x.js
regexTest
1) should return true if the string starts with a number
0 passing (10ms)
1 failing
As far as I remember there is no official way to repeat an assert statement, so running it inside a loop should be fine.
You might want to consider adding a more verbose failure message to your assert statement though, something like:
while(i++ <= 100) {
let testStr = Math.random().toString(36).substring(7);
assert.equal(true, regexTest(testStr), 'Test failed on ' + testStr);
}
(and just in case it helps, you don't need that if block in your regexTest function. Simply end with return match && match.length)
If you assert at every single execution of the loop, test will end at first assertion error. If you want to see how many times your test failed out of 100, you can store test results in an array, you can do something like:
var assert = require('assert');
describe('regexTest',function() {
it('should return true if the string starts with a number',function() {
var i = 1;
var errorsArray = [];
while(i++ <= 100) {
var randomNumber = Math.random();
if(!randomNumber.toString(36).substring(7)){
errorsArray.push(randomNumber);
}
}
assert.equal(0, errorsArray.length, errorsArray);
});
})
The problem with the code you have is that you are actually only testing the last random string generated.
Also, as mentioned by #Geotob, it will nicer if you print the string on which the test case failed.
You could frame it like:
var assert = require('assert');
function makeTest() {
describe('regexTest', function () {
var i = 0;
while (i++ <= 20) {
it('should return true if the string starts with a number', function () {
var i = 0;
let str = Math.random().toString(36).substring(7);
let output = regexTest(str);
assert.equal(true, output, `Failed on ${str}`);
});
}
});
}
function regexTest(randStr) {
let match = randStr.match(/^\d+/);
if (match && match.length > 0) {
return true;
} else {
return false;
}
}
makeTest();
This should work fine.
Notes:
Dynamically generating tests from the mocha doc.
Related
Am able to generate a random string in protractor node js BDD framework.But the problem is, the same value is being hold for all the scenarios when batch execution is triggered and the tests are getting failing because of the same value used in all the scenarios.Can someone please suggest how to generate new random value everytime a scenario is invoked during batch execution and the same value should be passed for all the methods for that scenario.
Note : I have declared it as global variable to be used across the methods for a particular scenario.
this
// 1.spec.js
let generateString = (length) => {
let letters = 'abcdefghijklmnopqrstuvwxyz',
str = '';
for (let i = 0; i < length; i++) {
str += letters[Math.floor(Math.random() * letters.length)];
}
return str;
}
let randomString = generateString(7);
describe(`Scenario`, () => {
it('1', async () => {
console.log(randomString);
});
it('2', async () => {
console.log(randomString);
});
it('3', async () => {
console.log(randomString);
});
});
will produce this
Jasmine started
saxijqt
Scenario
✓ 1 (0.014 sec)
saxijqt
✓ 2 (0.035 sec)
saxijqt
✓ 3 (0.01 sec)
I want to check if request has a string then response has to contain this string in postman. I write a test like this but it doesn't work for me. I'm not sure I can use multiple pm.expect in one test with condition. My code is
pm.test("test",function(){
var hasA = data.hasOwnProperty('A');
var hasB = data.hasOwnProperty('B');
if(hasA === true){
pm.expect(response.A).to.eql(data.A);
}
if(hasB === true){
pm.expect(response.B).to.eql(data.B);
}});
Request can contain A and B both so I cannot use if..else statement. When I run this test if hasA flag true then code doesnt go into for second if even hasB option is true. How can I handle this problem.Can anyone help?
expect is hard assertion so if one fails then it won't goto next one so you can use any of the below approach:
try if conditions like:
pm.test("test", function () {
var hasA = data.hasOwnProperty('A');
var hasB = data.hasOwnProperty('B');
var hasBoth = hasA && hasB
if (hasBoth) {
pm.expect([response.A, response.B]).to.eql([data.A, data.B]);
} else if (hasA) {
pm.expect(response.A).to.eql(data.A);
} else if (hasB){
pm.expect(response.B).to.eql(data.B);
}
});
or
try catch like :
pm.test("test", function () {
var hasA = data.hasOwnProperty('A');
var hasB = data.hasOwnProperty('B');
let error = {};
try {
if (hasA) {
pm.expect(response.A).to.eql(data.A);
}
} catch (e) {
error.A = e
}
try {
if (hasB) {
pm.expect(response.A).to.eql(data.A);
}
} catch (e) {
error.B = e
}
if(Object.keys(error).length){
pm.expect.fail(JSON.stringify(error))
}
});
I'm trying to run some JavaScript code on Postman, but I can't find a way for it to run in the order that I need. This is what I'm trying to do:
Retrieve the API response and verify if the "pending" array contains any item
If id does, I'll save the id of the record (orderId) in an environment variable to use in my actual request
At this point I would set found = true and break the loop when it leaves the setTimout function
Note: I created the function to introduce 400ms delay between the attempts, as it will allow the pending array to be populated
var found = false;
var counter = 0;
while (counter < 10) {
setTimeout(async () => {
var size = await response.json().pending.length;
if (size > 0) {
var orderId = response.json().pending[0].orderId;
pm.environment.set("current_order", orderId);
found = true;
}
}, [400]);
console.log(found);
if (found) { break; }
counter++;
}
My problem is that the part that is outside the setTimeout function executes first, so it will never satisfy the condition "If (found)". It always executes the code 10 times, even if the record is found in the first attempt.
My question is: How can I write it in order to check if the record was found after each attempt and break from the loop if positive?
Thanks!
As suggested above, you might be able to solve this issue with a simpler recursive function. An example on how it would look:
var found = false;
var size = 0;
async function checkResponse() {
var size = await response.json().pending.length;
if (size > 0) {
var orderId = await response.json().pending[0].orderId;
pm.environment.set('current_order', orderId);
found = true;
}
if (!found) {
await checkResponse();
}
}
await checkResponse();
Here is a synchronous test for the logic above:
var found = false;
// var size = 0;
var size = -5;
function checkResponse() {
// var size = await response.json().pending.length;
size += 1;
console.log(size);
if (size > 0) {
// var orderId = response.json().pending[0].orderId;
// pm.environment.set('current_order', orderId);
console.log("pm.environment.set('current_order', orderId);");
found = true;
}
console.log('END?');
console.log(found);
if (!found) {
checkResponse();
console.log('checkResponse();');
}
}
checkResponse();
Output:
-4
END?
false
-3
END?
false
-2
END?
false
-1
END?
false
0
END?
false
1
pm.environment.set('current_order', orderId);
END?
true
checkResponse();
checkResponse();
checkResponse();
checkResponse();
checkResponse();
I am using the JavaScript testing framework, Protractor.
I have an external utility class file that I am using to organize common logic within my test specs. See Using Page Objects to Organize Tests.
There seems to be an issue when I take a block of code that resolves a promise, and put in into my Helper utility class file, for the same use.
Example:
In an individual spec file, this code works as expected:
test.spec.js:
it('should display the Protractor workflow text', function() {
// match variable
var match = false;
// get elements by tag
var scanElements = element.all(by.css('div')).each(function(el) {
el.getText().then(function(text) {
var sp = text.split(' '); // split by <space>
for (var i = 0; i < sp.length; i++) {
if (sp[i] == 'Protractor') {
match = true;
}
}
});
});
// on complete
scanElements.then(function() {
console.log(match); // returns true
});
});
However, if I separate this logic into my Helper utility class, the return value is undefined.
Helper.js
/** containsText [process]
* searchs for text in tag elements (i.e. 'string' in <a>, 'string' in <div>)
* #param string - tag name to limit
* #param string - string value to search against
*
* #return boolean - if string is found
*/
this.containsText = function (tagName, stringValue) {
// match variable
var match = false;
// get elements by tag
var scanElements = element.all(by.css(tagName)).each(function(el) {
el.getText().then(function(text) {
var sp = text.split(' '); // split by <space>
for (var i = 0; i < sp.length; i++) {
if (sp[i] == stringValue) {
match = true;
}
}
});
});
// on complete
scanElements.then(function() {
return match;
});
}
test.spec.js
it('should display the Protractor workflow text', function() {
console.log(helper.containsText('div', 'Protractor')); // does not wait to resolve, returns undefined
});
Edit: All of the links to similar questions on Stack Overflow have to deal with asynchronous calls via Ajax requests. I'm looking for a solution for the Protractor / Webdriver framework. I have read documentation on creating promises with Protractor, and have tried the following as well:
Helper.js
this.containsText = function (tagName, stringValue) {
// get elements by tag
var scanElements = element.all(by.css(tagName)).each(function(el) {
el.getText().then(function(text) {
var sp = text.split(' '); // split by <space>
for (var i = 0; i < sp.length; i++) {
if (sp[i] == stringValue) {
return true; // fufill outer promise and break execution
}
}
});
});
return scanElements;
}
test.spec.js
helper.containsText('div', 'Protractor').then(function(f) {
console.log(f);
});
Still looking for some assistance.
I can’t figure out what is missing so that when e-mail is valid it will skip the last invalid message and move to next item on form for validation:
enter code here
if (document.form1.email.value.length > 0) {
var tst = document.form1.email.value;
var okd = ['bankofamerica.com','baml.com','magner.com','ml.com','ust.com','ustrust.com']
for (var i = 0; i < okd.length; i++) { okd[i] == okd[i].toLowerCase() }
var emailRE = /^[a-zA-Z0-9._+-]+#([a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})$/
var aLst = emailRE.exec(tst)
if (!aLst) {
alert(tst + ' is not a valid e-mail')
} else {
var sLst = aLst[1].toLowerCase()
for (var i = 0; i < okd.length; i++) {
if (sLst == okd[i]) {
// alert(aLst[1] + ' is allowed');-->
}
}
if (i == okd.length) alert(aLst[1] + ' is not allowed. Please enter an email address with an authorized domain.')
document.form1.email.select();
return false;
}
}
I'd recommend placing this code into a function, maybe named ValidateEmail().
In your loop: if you've determined the email is valid, return true;. This will prevent further execution. If that domain doesn't match, have it continue looping to check the others.
If the loop completes without returning true, you'll know it didn't match anything so return false; at the very end.
EDIT: Use try/catch instead:
if (document.form1.email.value.length > 0) {
var tst = document.form1.email.value;
var okd = ['bankofamerica.com','baml.com','magner.com','ml.com','ust.com','ustrust.com']
for (var i = 0; i < okd.length; i++) { okd[i] == okd[i].toLowerCase() }
try {
var emailRE = /^[a-zA-Z0-9._+-]+#([a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})$/
var aLst = emailRE.exec(tst)
if (!aLst)
throw (tst + ' is not a valid e-mail');
// isValidDomain will be changed to 'true' only if it matches an item in the array
var isValidDomain = false;
var sLst = aLst[1].toLowerCase()
for (var i = 0; i < okd.length; i++) {
if (sLst == okd[i]) {
isValidDomain = true;
// We break here because a match has been found - no need to compare against the other domain names.
break;
}
}
if(!isValidDomain)
throw (aLst[1] + ' is not allowed. Please enter an email address with an authorized domain.');
// If execution reaches here, you know it passed both tests!
return true;
}
catch(err) {
// This code block runs whenever an error occurs
alert(err);
document.form1.email.select();
return false;
}
}
throw basically acts like a goto command. It will jump directly to the catch(err) portion of the code.
More info about try, catch, and throw:
http://www.w3schools.com/js/js_try_catch.asp
http://www.w3schools.com/js/js_throw.asp
Thank you very much Colin!
I had to remove the following 2 lines to avoid halting the code from running on to next validation field:
isValidDomain = true;
// We break here because a match has been found - no need to compare against the other domain names.
// break - exits code from running on down to next item on page
}
}
if (!isValidDomain)
throw (aLst[1] + ' is not allowed. Please enter an email address with an authorized domain.');
// If execution reaches here, you know it passed both tests!
// return true; - was not needed, stops code from running on page
}
catch (err) {