I'm new to Mocha. I want to call Test case 2 from a.js file to b.js like import the test case because of same test cases repeatable in the b.js file. Example
File a.js :
describe('Sample a',function(){
it('Test case1',function(done){
console.log('Testing test case1');
});
it('Test case2',function(done){
console.log('Testing test case2');
});
it('Test case3',function(done){
console.log('Testing test case3');
});
});
File b.js:
describe('Sample b',function(){
it('Test case2',function(done){
console.log('Testing test case2');
});
});
Kindly provide the solution for this problem.
Thanks
There's no facility in Mocha to allow one test (it) to invoke another test or to allow a suite (describe) to invoke a test in another suite.
When you have tests that share logic, the solution is the same as any other two pieces of JavaScript code that share logic: refactor the code so that the shared logic is moved to a function that can be called, and call it from the code that needs it. Since your tests are in different files, you are going to have to import the shared code in your test files. You can use a loader like RequireJS or SystemJS to load the code at runtime, or use a bundler like Webpack or Browserify to pack your modules into a single bundle.
Related
Just starting a new UI testing project, and wonder if there is any best practice to organize the Cypress end-to-end test structure? For example - 1) embedded inside the source (under integration/...) or 2) separate file folder for this project?
Looking for some general guidelines and best practice. Thanks.
It is up to you where you want to keep your test files there is no one single rule (Read this). In case you're writing the tests under integration folder, you don't have to do add any additional configurations as cypress by default searches for the test suite files from inside the integration folder. Also, in case if you decide to write your tests inside some other folder, you can add the required configurations in your cypress.json file and you are good to go.
This is how my folder structure inside integration folder looks like:
Locators contain all locators, so that they can be managed from a single place. Inside that I have a file called selectors.js
Module 1 and Module 2 contains the test suites asper the modules.
Example of the selectors.js file:
export default {
toDoBtn: 'button[type="submit"]',
input: 'form > input',
listItems: 'ul > li'
};
Example of the test suite:
import selectors from '../../integration/Locators/selectors.js';
describe('Add Items in todo list and Validate', () => {
before(function () {
cy.pageIsLoaded(selectors.toDoBtn) //This is a custom command
})
beforeEach(function () {
cy.fixture('testdata.json').then(function (testdata) {
this.testdata = testdata
})
})
it('Add Items', function () {
cy.addItems(selectors, this.testdata) //This is a custom command
})
it('Validate Added Items', function () {
cy.validateItems(selectors, this.testdata) //This is a custom command
})
})
It's obviously a matter of opinion, but here's what guides me
end-to-end tests are not as tightly coupled to source files as unit tests, so it makes sense to place them in a separate folder structure
you tend to work on a bunch of source files to build a feature, then write an e2e to test that feature, which points to a feature hierarchy
Cypress allows for non-standard test location, but be wary as third party plugins (which you may add late in the project) may not
Cypress commands are quite expressive, so it does not make sense to write custom commands for everything (simple is better than complex)
named selectors are expressive, but keep them local (inside the spec file) as they will differ subtly from one page to another. Better still, ditch selectors and use a search tool like cypress-get-it
So, I have a beforeEach to load up my site. I am mainly writing my test in one describe function with one it function.
my beforeEach is in the index.js>Support>Cypress folder
beforeEach(() => {
cy.visit('http://localhost:3000/');
});
Current Code Example:
describe('this is a test',function(){
it('will be a test example',function(){
cy.contains('test').click
cy.contains('another test').click()
})
})
A co worker pointed out that I should try to break them up to be more clear on what each test is doing so long as each part can run independently. I have several tests that can run independent, however, the beforeEach kicks in for each it('test_name',function() I write.
For example: I write a test to open a card, click on a state, add data about that state, then close. If I break each part into it's own it then it will have the beforeEach start back on the "home" page of my site.
Example of desired code:
describe('this is a test',function(){
it('will be a test example',function(){
cy.contains('test').click
})
it('will test another test',function(){
cy.contains('another test').click()
})
})
Is there a way for those several it functions to continue on the previous test rather than having the beforeEach effect it?
Thank you in advance.
You can use beforeEach() and before(). The behaviour of both is slightly different.
before() only applies once per describe()
beforeEach()applies for every it() in the describe()
Thus what you have to do:
Put all steps you want to only perform once per describe()in a before(). If there are still steps left which you want to perform every it(), put those in a beforeEach().
Note that you can use both before() and beforeEach() together.
I've splitted my project from one huge test to a few smaller to speed up tests and avoid some errors. Is there any way to run all of them parallel with single conf file? I must pass through login.js before every testcase
specs: ['login.js', 'test1.js'],
I suggest changing your login.js spec into a file which exports a login function. Then create a beforeAll in your onPrepare in your conf. This will be executed before every describe block, which in your case is every test.
onPrepare: function {
beforeAll(function(){
loginToApp();
});
};
I know you have already split up the files but I would seriously consider using the page object model to structure your tests if you have the time.
Is it possible to use something other than reflection and the [Fact] attribute on a test method to expose tests to xUnit test runner? For example, I'd like to do something like:
[FactSource] // just making this up
public IEnumerable<ITest> GetUnitTests()
{
yield return new TestCase("test case 1", () => FooAssertion());
yield return new TestCase("test case 2", () => BarAssertion());
}
I've wanted to do this many times to reduce the boilerplate of a function to wrap every single case. Usually it makes sense, but when I am testing 100 API endpoints it's the difference between a file with 100 lines vs. 400 lines of code. Also, I have cases where I want to load the tests from a .JSON or .XML file so it would be great if there was another way to load the tests rather than just [Fact] or [Theory] attributes.
NOTE: [Theory] works great for some tests like this, but it doesn't work for loading the cases from a file or for the case I demonstrate above where I am using lambda expressions.
Thank you!
Check out Exude. It does exactly what you want.
I started using Protractor and the first thing I've tried to do is to use Mocha and Chai instead of Jasmine. Although now I'm not sure if that was a good idea.
first I needed to make Chai accessible from all the spec files, without having to import everytime, I found it's possible to do in protractor.conf file:
onPrepare: ->
global.chai = require 'chai'
chai.use require 'chai-string'
chai.use require 'chai-as-promised'
global.expect = chai.expect
now in a spec like this:
it "when clicked should sort ",->
headerColumns.get(0).click()
firstCellText = $$(".first-cell").getText()
secondCellText = $$(".second-cell").getText()
# this won't work
expect(firstCellText).eventually.be.above(secondCellText)
to make it work I could do:
# now this works
$$(".second-cell").getText().then (secondCellText)->
expect(firstCellText).eventually.be.above(secondCellText)
but that's ugly, and I don't want to wrap stuff inside of .then all the time. I'm thinking there should be a better way(?)
I was having the same problem. The issue for me was to add a longer timeout to mocha through the Protractor config.js.
This works because Protractor tests take considerably longer relative to other modules like supertest since an actual browser is being interacted with.
I added
mochaOpts: {
timeout: 5000
}
to my protractor config and the tests passed.
Either you need to mention timeout for the whole test suite using "this.timeout(1000);" just below the describe block, or you can change it for individual test cases by explicitly defining timeout for each "it" block.
example for describe block:
describe("test-suite",function () {
this.timeout(5000);
it("test-case",function () {
//test case code goes here
});
});
example for it block:
it("test-case",function () {
this.timeout("20000");
});
I found this question while I was trying to do the same thing in TypeScript, but the approach in the protractor.conf.js is identical.
Making chai available globally
It appears to achieve this you're right that it needs to be done in the on prepare. a fairly terse example is below. As I understand it this is needed because chai is of course not apart of mocha but some additional candy that we can use with mocha. Unlike jasmine where everything is bundled into the framework.
protractor.conf.js fragment
onPrepare: function() {
var chai = require('chai'); // chai
var chaiAsPromised = require("chai-as-promised"); // deal with promises from protractor
chai.use(chaiAsPromised); // add promise candy to the candy of chai
global.chai = chai; // expose chai globally
}
example spec
Once you've got chai and chai-as-promised setup globally you need to add a "little" boiler plate to your spec to expose expect which comes from chai.
example.e2e-spec.ts fragment
const expect = global['chai'].expect; // obviously TypeScript
it('will display its title', () => {
pageObject.navigateTo();
const title = element(by.css('app-root h1')).getText();
expect(title).to.eventually.contain('An awesome title');
});
Avoiding then
I can't tell what your $$ references are, but if you're using the protractor components browser and by etc. then things clean up a little bit.
The call const title = element(by.css('app-root h1')).getText(); seems to return a promise which jasmine seems to deal with out of the box while mocha+chai doesn't. That's where chai-as-promised comes in.
using our additional syntax candy expect(title).to.eventually.contain('An awesome title'); resolves the promise quite neatly and we've avoided all those then calls, but we do need the eventually.
I've provided you a link to a working TypeScript example that might help demonstrate.