Using tags ( Smoke, regression) with TestCafe - testing

Using testcafe grep patterns would partially solve our problem of using tags but it would still display those tags on the spec report ...!!!
Is there a way to include tags in the test/fixture names and use grep patterns but skip those tags to be displayed in the execution report ??
import { Selector } from 'testcafe';
fixture `Getting Started`
.page `http://devexpress.github.io/testcafe/example`;
test('My first test --tags {smoke, regression}', async t => {
// Test code
});
test('My Second test --tags {smoke}', async t => {
// Test code
});
test('My first test --tags {regression}', async t => {
// Test code
});
testcafe chrome test.js -F "smoke"
The above snippet would trigger the smoke only tests for me though but the report will display the test names along with those tags
Is there an alternative way to deal with tags or a solution to not display the tags in the test execution report?

It appears in a recent release (v0.23.1) of testcafe you can now filter with metadata via the commandline.
You can now run only those tests or fixtures whose metadata contains a specific set of values. Use the --test-meta and --fixture-meta flags to specify these values.
testcafe chrome my-tests --test-meta device=mobile,env=production
or
testcafe chrome my-tests --fixture-meta subsystem=payments,type=regression
Read more at https://devexpress.github.io/testcafe/blog/testcafe-v0-23-1-released.html

I think the best solution in this case is to use test/fixture metadata. Please refer the following article: http://devexpress.github.io/testcafe/documentation/test-api/test-code-structure.html#specifying-testing-metadata
For now, you can't filter by metadata, but this feature is in the pull request: https://github.com/DevExpress/testcafe/pull/2841. So, after this PR is merged, you will be able to add any metadata to tests and filter by this metadata in a command line.

Related

TestCafe unable to use testController (t) outside of test run (e.g. as a conditional to skip a test)

I'm trying to check which browser we're running tests on, and then skip a test/fixture based on the result (as mentioned in this TestCafe Issue).
import { t } from 'testcafe';
fixture `test`
.page('https://testcafe.devexpress.com')
if (t.browser.name.includes('Chrome')) {
test('is Chrome?', async () => {
console.log(t.browser.name);
await t.expect(t.browser.name.includes('Chrome').ok();
});
} else {
test.skip('is Chrome?')
};
Results in...
ERROR Cannot prepare tests due to an error.
Cannot implicitly resolve the test run in the context of which the test controller action should be executed. Use test function's 't' argument instead.
Is there any way I can call the testObject (t) outside of the test?
I don't have a solution to exactly your question. But I think it's better to do it slightly differently, so the outcome will be the same, but the means to achieve it will differ a bit. Let me explain.
Wrapping test cases in if statements is, in my opinion, not a good idea. It mostly clutters test files so you don't only see test or fixture at the left side, but also if statements that make you stop when reading such files. It presents more complexity when you just want to scan a test file quickly from top to bottom.
The solution could be you introduce meta data to your test cases (could work well with fixtures as well).
test
.meta({
author: 'pavelsaman',
creationDate: '16/12/2020',
browser: 'chrome'
})
('Test for Chrome', async t => {
// test steps
});
Then you can execute only tests for Chrome like so:
$ testcafe --test-meta browser=chrome chrome
That's very much the same as what you wanted to achieve with the condition, but the code is a bit more readable.
In case you want to execute tests for both chrome and firefox, you can execute more commands:
$ testcafe --test-meta browser=chrome chrome
$ testcafe --test-meta browser=firefox firefox
or:
$ testcafe --test-meta browser=chrome chrome && testcafe --test-meta browser=firefox firefox
If your tests are in a pipeline, it would probably be done in two steps.
The better solution, as mentioned in one of the comments in this question is to use the runner object in run your tests instead of the command line. Instead of passing the browser(s) as a CLI argument, you would pass it as an optional argument to a top-level script.
You would then read the browser variable from either the script parameter or the .testcaferc.json file.
You would need to tag all tests/fixtures with the browser(s) they apply to using meta data.
You then use the Runner.filter method to add a delegate that returns true if the browser in the meta data is equal to the browser variable in the top level script
var runner = testcafe.createRunner();
var browser = process.env.npm_package_config_browser || require("./testcaferc.json").browser;
var runner.filter((testName, fixtureName, fixturePath, testMeta, fixtureMeta) => {
return fixtureMeta.browser === browser || testMeta.browser === browser ;
}

How to call another test during my test in Cypress

I have a problem when creating test with Cypress
I am creating a test to which is required that the user should be in logged on his account to be able to run the test.
I have another test to test the log in function.
How can I run the test (Create account) so i dont need to have the code in the beginning of every test to log in first as in the example.
I start always with the log in script before I run the test.As u see I have the username and the password for each test.
I want to be able to run the log in first and then the rest.
cy.visit('https://devcloudarena.devtest.fastighet.vitec.se/test/mina-sidor/logga-in')
cy.contains('Mina sidor').click()
cy.contains('Logga in').click()
cy.get('#UserId').click();
cy.get('#UserId').type('19380412-6526');
cy.get('#Password').click();
cy.get('#Password').type('Vitec.Test20');
cy.get('.ml-auto > .button').click();
cy.wait('#getActivities').then((xhr) => { });
cy.url().should('contains', 'https://devcloudarena.devtest.fastighet.vitec.se/test/mina-sidor');
cy.get('.d-block .col-9').click();
cy.url().should('contains', 'https://devcloudarena.devtest.fastighet.vitec.se/test/mina-sidor/min-profil');
cy.get('.object-description-cc > a').click();
cy.url().should('contains', 'https://devcloudarena.devtest.fastighet.vitec.se/test/mina-sidor/uppdatera-kontaktuppgifter');
cy.get('.form-group > .button').click();
cy.get('#RegisterForm').submit();
cy.url().should('contains', 'https://devcloudarena.devtest.fastighet.vitec.se/test/mina-sidor');
You can put it as a Custom command and it will be reusable in every test with a simple command call.
To add to Rosen Mihaylov's answer, the user could convert the login script into a custom command and also use hooks to implement the pre-condition of the test by calling that specific custom command.
custom command pertaining to support/command.js
Cypress.Commands.add('login', (email, pw) => {})
using the custom command in the spec file
beforeEach(() => {
cy.login()
})

Unable to call a function from Fixture.before Method

I am trying to implement a fixture with multiple tests where all depend on each other
Therefore I want to clean the Database and perform login only one time from the Fixture.before Method
So it will look like this:
fixture `testProject`.page(baseUrl)
.before(async t => {
await loginPM.login()
await base.clearDB()
})
.beforeEach(async t => {
// some steps before each test
})
test 1
test 2
test 3
This scenario throws the following exception:
Error in fixture.before hook - Cannot implicitly resolve the test run in the context of which the test controller action should be executed. Use test function's 't' argument instead
Any ideas why testcafe not support calling functions from a Fixture.before Method
The fixture.before hook runs between tests and doesn't have access to the tested page. Please refer to the following help topic for details on its use: Fixture.before Method. If you need to execute test actions (click, typeText, etc) once per fixture before you start all tests, see this module: testcafe-once-hook module. Here is an example of how to use it: https://github.com/AlexKamaev/testcafe-once-hook-example.

Old step definition is retained in WDIO Allure reports

I got a situation in webdriverIO allure reporter. When a feature file and step definition is defined for the first time and run, Allure report is generated as expected.
If the existing step is modified in feature and step def files, Allure report will show the old step and the newly modified step which is misleading.
Sharing an example of the above scenario,
Feature file: test.feature
Feature: Cucumber proof of concept
Background:
Given I navigate to Google
Scenario: First Scenario
When I search for "Formula 1"
Scenario: Second Scenario
When I search for another result "Grand Prix"
Step def file: test.js
let {defineSupportCode} = require('cucumber');
defineSupportCode(function({Given, When, Then}) {
Given(/^I navigate to Google$/, () => {
browser.url('http://www.google.com')
});
When(/^I search for \"([^\"]*)\"$/, (text) => {
browser.setValue('#lst-ib', text);
browser.pause(5000);
});
When(/^I search for another result \"([^\"]*)\"$/, (text) => {
browser.setValue('#lst-ib', text);
browser.pause(5000);
});
});
The allure report is as expected
enter image description here
Later if I modify step of the Second scenario to be,
Scenario: Second Scenario
When I search for another new result "Grand Prix"
and generate Allure report, the old and the modified steps will be seen as shown below,
enter image description here
I know that Allure2 supports history. But this is quite confusing and even the order in 2nd Scenario is messed up.
The only way to I was able to fix this was by deleting allure-results folder whenever there is a modification of a step. But I can't do that since I need the trend in Jenkins. Is there a way to get around this issue.
Platform:
Windows 10
package.json -
"webdriverio": "^4.12.0"
"wdio-cucumber-framework": "^1.1.1"
"wdio-allure-reporter": "^0.6.2"
Please try to use --clean option when generating allure report:
allure generate --clean

Protractor - How to separate each test to one file and separate variabiles

I have some komplex protractor test written but everything is in one file.
Where I'm on top of it loading all variabiles like:
var userLogin = "John";
and after that somewhere in code I use it together.
What I need to do is
1. Separate all variabiles to aditional file (some config file)
2. Each test to one file
1- I try to make config.js where I add all variabiles and i required it in protractor.conf.js it load correctly problem is that when i use any of this variabiles in some test it's not working (test fail with "userName is not defined")
I know there is a way where i requre config.file in each test script but that's really not best option in my eyes.
2- How can I know what I did in last script if it's separate, like for example how to know I am logged in?
Thanks.
There are multiple things you can make use of.
2) How can I know what I did in last script if it's separate, like for example how to know I am logged in?
This is where beforeEach(), afterEach() can help:
To help a test suite DRY up any duplicated setup and teardown code,
Jasmine provides the global beforeEach and afterEach functions. As the
name implies, the beforeEach function is called once before each spec
in the describe is run, and the afterEach function is called once
after each spec.
There are also beforeAll(), afterAll() available in jasmine 2, or via jasmine-beforeAll third-party for jasmine 1:
The beforeAll function is called only once before all the specs in
describe are run, and the afterAll function is called after all specs
finish. These functions can be used to speed up test suites with
expensive setup and teardown.
1) I try to make config.js where I add all variabiles and i required
it in protractor.conf.js it load correctly problem is that when i use
any of this variabiles in some test it's not working (test fail with
"userName is not defined") I know there is a way where i requre
config.file in each test script but that's really not best option in
my eyes.
One option which I've personally used would be to create a config.js file with all the reusable configuration variables you would need in multiple tests and require the file once - in the protractor config - then set it as a params configuration key value:
var config = require("./config.js");
exports.config = {
...
params: config,
...
};
where config.js is, for example:
var config;
config = {
user: {
login: "user",
password: "password"
}
};
module.exports = config;
Then, you would not need to require config.js in every test, but instead, you'll use browser.params. For example:
expect(browser.params.user.login).toEqual("user");
Also, if you need some sort of a global test preparation step, you can do it in onPrepare() function, see Setting Up the System Under Test. Example configuration that performs a "global" login step is available here.
And an another quick note: you can have custom globally defined variables (like built-in browser or protractor), set them using global in onPrepare. For example, I've defined protractor.ExpectedConditions as a custom global variable:
onPrepare: function () {
global.EC = protractor.ExpectedConditions;
}
Then, in tests, don't require anything, `EC variable would be available in the scope, e.g.:
browser.wait(EC.invisibilityOf(scope.page.dropdown), 5000)
Also, organizing your tests using "Page Object Pattern" would also help to solve the reusability and modularity problem.