Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add BeforeStep / AfterStep hooks #997

Closed
charlierudolph opened this issue Jan 4, 2018 · 33 comments
Closed

add BeforeStep / AfterStep hooks #997

charlierudolph opened this issue Jan 4, 2018 · 33 comments

Comments

@charlierudolph
Copy link
Member

Useful for validations after every step ends. this should be the world instance

@khanali21
Copy link

@charlierudolph I would like to help here, but need some pointer on the appropriate way implement it. I believe there was syntactic sugar AfterStep for registerHandler which was removed recently. I looked at support_code_library_builder/define_helpers.js. But need some pointers on how to implement these hooks.
thanks
Ali
P.S. Thanks for reverting the result json format.

@charlierudolph
Copy link
Member Author

charlierudolph commented Jan 4, 2018

A question here though is how does this effect the workflow? Can this edit the step result status or does it act as another step that can pass / fail?

@khanali21
Copy link

The use case that I have seen in one of the comments and which I also want to use is to create a screenshot after the step. In cucumber ruby I have used the AfterStep which provides access to the Scenario object.
IMHO the afterstep hook should only be used for use cases where user want to introspect the step result but should not be able to change the result. I also think that it should not another step which can pass/fail.

@mracz
Copy link

mracz commented Jan 29, 2018

@charlierudolph I'm looking for a similar solution as well.
Before the registerHandler became deprecated, i used this code to take screenshot after failed steps.:

this.registerHandler('StepResult', function (event, callback) {
    var stepResult = event.getPayloadItem('stepResult');

    if (stepResult.getStatus() == 'failed') {
      takeScreenshot()
        .then(function () {
          callback();
        });
    } else {
      callback();
    }});

Now I don't have solution for this.

@markus-lundin-86
Copy link

Hi,

I have seen in most threads i read regarding BeforeStep/AfterStep hook that the use-case is taking a printscreen. This is not my use-case and I just want to voice other use cases for these hooks:

My project have used this.AfterStep hook in cucumber 1.x for:

  • collecting data - such as all external links:
    element.all(by.css('a')).each(function(link) { link.getAttribute('href').then(function(href) { ... }); });

All external links are then tested in a separate test-suit.

  • Checking for element ID duplicates (purpose is to make sure all ID's are unique to comply with HTML standard and also makes creating tests easier)
  • Checking for script error's (AfterStep would set a variable for After hook to actually fail scenario).
  • Disregarding browser alerts. A few test-scenarios makes web-browser open alert window which we may want to disregard. This especially applies when there are form and input elements, browser will alert ("You have unsaved changes...")

Currently using Cucumber 4.0.0 and Protractor 4.0.14

Side-note: Our use cases did not work properly with this.AfterStep() in Cucumber 1.x.x because it was not designed to have this type of code in it and we saw problems with race-conditions. So we have upgraded to Cucumber 4.0.0 and disabled AfterStep logic until there is proper support for it.

@gajo4256
Copy link

gajo4256 commented Mar 14, 2018

Hi,

any updates regarding this before/after step hooks?
Is there any workaround for AfterStep hook? I would like to take a screenshot if the particular test had failed.

"attach" is not available for me because we have overridden the default World constructor https://github.com/cucumber/cucumber-js/blob/master/docs/support_files/world.md

Thnx

@mracz
Copy link

mracz commented Mar 14, 2018

Hi @gajo4256,

I'm using cucumber 4.0.0 and this snippet:

After(function (scenario) {
  if (scenario.result.status === Status.FAILED) {
    const World = this;

    return browser.takeScreenshot().then(function (buffer) {
      return World.attach(buffer, 'image/png');
    });
  }});

This will take a screenshot after every failed scenario. ( It works for me, because with cucumber, whenever a step fail, the whole scenario will fail, so it is almost identical with "after step fail".

Hope it helps.

@gajo4256
Copy link

Hi @mracz,

thnx, I actually tried this (although after each step would it would be more suitable for me).
Since I have overridden the default World constructor, how can I have attach again available for me as it is in normal case?

Thnx

@mracz
Copy link

mracz commented Mar 14, 2018

Hi @gajo4256,

This is what i have in my Custom world implementation:


const { setWorldConstructor } = require('cucumber');

function CustomWorld( { attach } ) {
  this.attach = attach;
}

setWorldConstructor(CustomWorld);

@rkrisztian
Copy link

rkrisztian commented Mar 29, 2018

@mracz, I currently do this for each step:

	When('I do something', function () {
		return takeScreenshot(this, () => {
			return $(...).click();
		});
	});

Where the screenshot taking function is this:

export function takeScreenshot(world, stepToExecute: () => promise.Promise<any>): promise.Promise<any> {
	return stepToExecute().then(() => {
		return doTakeScreenshot(world);
	}).catch((err) => {
		return doTakeScreenshot(world).then(() => {
			throw err;
		});
	});
}

function doTakeScreenshot(world) {
	return browser.takeScreenshot().then((screenshot) => {
		world.attach(screenshot, 'image/png');
	}).catch((err) => {
		console.warn('Could not create screenshot', err);
	});
}

I may have been too defensive about exceptions, but I did my best that the extra code does not interfere with the real test results. Best I can do right now, a working AfterStep hook would make me add less boilerplate.

However, what the hook would probably not do is skipping screenshots when I'm making assertions that do not change the screen (thus the screenshot would be useless), e.g. Then some element is not shown. I guess an extendable world object could help out there.

@aslakhellesoy
Copy link
Contributor

Here is another use case for AfterStep hooks: Wait for peers to synchronise (using vector clocks or lamport timestamps). /cc @tooky @jbpros

@tunovic tunovic mentioned this issue May 18, 2018
@seean
Copy link

seean commented May 22, 2018

Hello everyone.
I'm actually working on this issue.

We are looking for a way to take screenshot from all our different steps.
Right now, we are thinking about overriding StepDefinitions function from cucumber.

Don't know if it is the best possible way so please, don't hesitate to give your opinion about it !

@anri-asaturov
Copy link

For anyone struggling here's a way to do this with definition function wrapper: https://github.com/PeerioTechnologies/peerio-icebear/blob/dev/test/e2e/code/hooks.js#L28

@KyleFairns
Copy link

KyleFairns commented May 22, 2018

Our main use case would be like others here: screenshots, but using it as more of a debugging tool so that we can see the output of each step if we turn on debugging mode in our configuration.

Another use: we have a few modals that may appear after certain lengths of time on our website. If we run through a scenario, we would want to have checks in place for those modals being on the page after every step to ensure our tests aren't fragile because of these modals.

Another use case: if someone wanted to create a reporting tool complete with dashboard (currently running test statuses, test cases that have been previously ran, etc), cucumber could post to the tool in the step hooks for an update on progress. It's an unusual example, I know, but it's something that I'm interested in looking into now that I've thought about it.

@kohesion
Copy link

KyleFairns, I need AfterStep for dashboard as you mentioned

@Klaas088
Copy link

Hello,

We want to check if there is any javascript error after each step. Not only the failed steps.
(Bit the same as @markus-lundin-86)
Now we can only do that after each scenario.
So is this on the road map, or has anyone has other solutions?

@kohesion
Copy link

kohesion commented Jun 7, 2018

I just discovered that WebDriverIO has beforeStep and afterStep hooks for cucumber which solves my problem.

Hope that helps...

@Prasant-Sutaria
Copy link

Hi All,

Any update on Step hooks? Or any work around for running some code before and/or after each step execution?

@bouillonpi
Copy link

Hi all,
In the same situation as @Prasant-Sutaria.
Any update on step hooks or workaround?
Thanks in advance.

@aslakhellesoy
Copy link
Contributor

No updates. Still waiting for someone to submit a pull request for this.

@FibreFoX
Copy link

Is there any roadmap or anything to this? As this is one major painpoint to have this feature, maybe an official statement would be nice.

@aslakhellesoy is there a checklist or something what a pull-request needs to implement? AFAIK #1058 and #1121 try to bring this feature, or some ways to workaround.

@Andras-Marozsi
Copy link

Hey guys,
I just created a PR regarding this issue: #1198.
Let me know if you find it useful.

@Andras-Marozsi
Copy link

Andras-Marozsi commented May 16, 2019

@aslakhellesoy, I've created the above PR (#1198) to address this issue/feature request. Can you please take a look at it, or point me to someone I should contact?
cc: @charlierudolph

@leonardonelson91
Copy link

any updates? looking forward to have it as well :)

@fescobar
Copy link

I see 2 PRs @leonardonelson91
I think they didn't find the best way to implement this feature
#1198
#1058

@davidjgoss
Copy link
Contributor

@charlierudolph do you have a view on whether the functions registered against BeforeStep and AfterStep should still be run if the step times out?

Like a few others here, I'm using setDefinitionFunctionWrapper to achieve the screenshots thing, which works great except I have no way in for when test steps time out - the best I can do is provide a shorter timeout to the browser instrumentation so it will throw whilst the step is still active. I am hoping to work on a fix for setDefinitionFunctionWrapper but wanted to know what the intent was here too.

@charlierudolph
Copy link
Member Author

charlierudolph commented Oct 9, 2019

I would expect that BeforeStep / AfterStep will run no matter what regardless of whether a step passes / fails (due to a timeout or otherwise)

@Philyorkshire
Copy link

Philyorkshire commented Dec 17, 2019

Just to add an additional use case to this which is not about screenshots. I am testing an event driven system and the tests cause events to be generated. Those events are then read and create changes to the system.

The steps which follow validate the system is in the expected state which requires all events to have been processed. I would like the ability to ensure the queue has been fully processed and there is nothing in pending state before moving to the next step.

Currently I am doing some polling of the event stream in validation steps, but it would be nice to just put it into a hook. As it is a ubiquitous requirement that the system is stable state before going to next step.

@RArkasali
Copy link

@davidjgoss @charlierudolph Please can you help me with a sample example code of setDefinitionFunctionWrapper for to achieve the screenshots thing BeforeStep/AfterStep?, I am trying with Nightwatch JS

@davidjgoss
Copy link
Contributor

Hi @RArkasali here's a snippet from a project I work on:

import {setDefinitionFunctionWrapper} from "cucumber";

setDefinitionFunctionWrapper(function(fn) {
    return async function(...args) {
        try {
            return await fn.apply(this, args);
        } catch (ex) {
            await this.takeScreenshot();
            throw ex;
        }
    };
});

(Where takeScreenshot is a method on your custom World that does the actual screenshot-taking stuff. I'm not familiar enough with nightwatch to know what that looks like but I'm sure you will be.)

So this will take a screenshot if there is an error (like an assertion failure) from within the step function. The fact that we return the result of a non-error one is important - I was confused for a while while a step with return "pending" wasn't being handled, until I realised I was swallowing the return value.

Hope this helps

@baor
Copy link

baor commented Mar 10, 2020

Hi all,
what is the status of this issue? Does it still needs help?
I am interested in BeforeStep and AfterStep, because it would help me to have a "log" file with all the step names and additional log information. It is a bit easier than creation of custom formatter.

@Adam-ARK
Copy link
Contributor

This has been added as apart of #1416

@Adam-ARK
Copy link
Contributor

Closing this issues since the hooks have been added in #1416

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests