Closed satyabrat105 closed 1 month ago
Please, try to reproduce the bug on https://github.com/vitalets/playwright-bdd-example and share the link here.
Also note that BeforeAll / AfterAll
are called in each worker.
Also note that BeforeAll / AfterAll are called in each worker
How can I ensure the whole featurefile is executed on the same worker?
Basically, I need to have a precondition for the featurefile, so it executes only once for this particular featurefile, but not for any other featurefile.
Thanks for the answer @maxtuzz. I've tried Background, and according to cucumber documentation and the behavior I was getting from using it - Background is executed before each test, not even once per worker, but strictly before each test. It seems the purpose of background is to avoid duplication in the first steps of scenarios.
How can I ensure the whole featurefile is executed on the same worker?
By default Playwright executes the whole file inside single worker, until you set fullyParallel option in the Playwright config.
The solution with Background
from @maxtuzz in general works (the comment is removed now). The downside - it requires additional code to ensure the background is executed only once (setting some global flag). For example:
Feature: Some feature
Background:
Given ensure user exists in database
Scenario: ...
Example of step implementation:
let executed = false;
Given('ensure user exists in database', async ({ page }) => {
if (!executed) {
executed = true;
// create user in database
}
});
Here user will be created only once before feature file.
Note: Although it works, I'm not fully satisfied with the approach. Global variables in hooks are not honored by Playwright team as well. The best approach is to migrate to Playwright fixtures. Or, if keep using hooks - it's better to explicitly mark code as executed before each feature, like we do for other hooks. I've made some research and created a proposal in #219.
That's what I'm trying to implement right now. The main issue here is that even global variables in the file, where I describe Background stepdefinitions are valid only within a single worker, therefore, these variables should be made even more global, and as an attempt I'm trying to use a file where I will track for which feature which precondition was executed. Even though I don't have parallel execution enabled the worker changes whenever the test fails (apparently, to ensure clean env for the next test start). Thanks for the suggestion about the fixtures, I will look into them to see if they fit the purpose.
import { createBdd,test} from 'playwright-bdd'; import {Browser,BrowserContext,Page} from 'playwright';
let browser:Browser; let context: BrowserContext;
const {BeforeAll,AfterAll,Before,After} = createBdd(test);
BeforeAll(async()=>{
browser= await invokeBrowser(); context= await browser.newContext();
});
AfterAll(async()=>{
await browser.close();
}); it's my hoook file, how can i use wroker in beforeall
Not sure how exactly you want to use worker, but you can access info about the current worker by declaring a hook like this:
BeforeAll(async ({$workerInfo}) => {
In the hook body, you can refer to this incoming parameter $workerInfo.
Even though I don't have parallel execution enabled the worker changes whenever the test fails (apparently, to ensure clean env for the next test start)
Yeap, this is the approach Playwright follows - if something fails, perform the whole setup from scratch. So with global variable, you may have extra run of background setup in case of fails. Isn't it suitable?
Hi vitalets, in my current playwright-bdd framework,its based on test level scope .for that, every execution beforeall method is executing. so i want a worker level scope. can you please give a example where worker level scope is used in hooks or in page fixture.
Even though I don't have parallel execution enabled the worker changes whenever the test fails (apparently, to ensure clean env for the next test start)
Yeap, this is the approach Playwright follows - if something fails, perform the whole setup from scratch. So with global variable, you may have extra run of background setup in case of fails. Isn't it suitable?
Not really. Example: In one of my cases, I'm creating several documents, that will be used later for testing the filter feature. Therefore, even if one of the tests fails I don't need to create another set of documents, so this extra run of background setup is not really acceptable.
In one of my cases, I'm creating several documents, that will be used later for testing the filter feature. Therefore, even if one of the tests fails I don't need to create another set of documents, so this extra run of background setup is not really acceptable.
Got it. With such external state, the only way I see - is to check inside the background step, are there documents created or not. If it's API call, you can create some lock file in the tmp dir after successful documents creation.
Even after #219 beforeFeature hook will rerun if something fails, here we should follow the Playwright's architecture.
Hi vitalets, in my current playwright-bdd framework,its based on test level scope .for that, every execution beforeall method is executing. so i want a worker level scope. can you please give a example where worker level scope is used in hooks or in page fixture.
const { BeforeAll, Before, Given } = createBdd();
BeforeAll(async function ({ $workerInfo, browser }) {
console.log("BeforeAll", $workerInfo.workerIndex, browser.browserType());
});
Before(async function ({ $testInfo, browser }) {
console.log("Before", $testInfo.workerIndex, browser.browserType());
});
Given('I open page', async ({ page, $testInfo, browser }) => {
console.log("Step", $testInfo.workerIndex, browser.browserType());
await page.goto(url);
});
In one of my cases, I'm creating several documents, that will be used later for testing the filter feature. Therefore, even if one of the tests fails I don't need to create another set of documents, so this extra run of background setup is not really acceptable.
Got it. With such external state, the only way I see - is to check inside the background step, are there documents created or not. If it's API call, you can create some lock file in the tmp dir after successful documents creation.
Even after #219 beforeFeature hook will rerun if something fails, here we should follow the Playwright's architecture.
This particular example relates to the UI tests, so checking the actual documents on UI will add some execution time.
I'm trying the approach of having a properties file in a file system, where the background steps will write something like:
Feature_1.Documents_Creation_Precondition=true
when this precondition is executed
If we go parallel at some point (at the moment there are some limitations of the system under test that prevent us from doing so) will also have to introduce some synchronization to operations with this file and add some info about the thread or something similar to the entries in the file.
so checking the actual documents on UI will add some execution time
You mean that you need to wait for documents to be loaded into browser UI? Shouldn't actual test steps (e.g. filter checks) wait for that anyway?
will also have to introduce some synchronization to operations with this file and add some info about the thread or something similar to the entries in the file
Or maybe even sqlite file to handle concurrency issues.
In one of my cases, I'm creating several documents, that will be used later for testing the filter feature. Therefore, even if one of the tests fails I don't need to create another set of documents, so this extra run of background setup is not really acceptable.
I've made a deeper search in Playwright issues for similar topic. There are many people, who have exactly the same reasonable request - run beforeAll
only once:
Lets track these issues, I hope Playwright will provide and option for that.
class MyPage{ constructor (public page:Page){} async openlink(name:string){ await this.page.getByRole('link',{name}).click(); } }
export cont test= base.extend<{},{pagefixture:MyPage}>({ pageFixture:[async({page},use)=>{ await use(new MyPage(page)); },{scope:'worker'}], });
Here i am trying use wroker scope then i am getting issue like property page doesnot exist. if i use testscope then there is no issue. but i required workerscope. how to do that in fixture ?
Here i am trying use wroker scope then i am getting issue like property page doesnot exist. if i use testscope then there is no issue. but i required workerscope. how to do that in fixture ?
Page is not available in worker scoped fixture, because page is re-created for each test. Imagine worker with 3 tests - which page instance should be passed into worker fixture, that is called after worker start?
as per playwright-bdd document :
import { createBdd } from 'playwright-bdd';
const { BeforeAll, AfterAll } = createBdd();
BeforeAll(async function ({ $workerInfo, browser }) { // runs when each worker starts });
please give some suggestion what i need to implement in beforeall, give some example
please give some suggestion what i need to implement in beforeall, give some example
In BeforeAll you can make some setup that needed once in each worker. I think BeforeFeature / AfterFeature will be more useful, so keep track of this issue https://github.com/vitalets/playwright-bdd/issues/219
@satyabrat105 is this issue resolved ?
In my project , i have one featurefile, 7 scenarios. in hooks i am using beforeall,before,after,afterall. when i executed the featurefile, before every scenario it is executing beforeall and after complete the scenario it executed afterall. 7times it executed beforeall and afterall. am i doing wrong? plaese share your feedback .