I have the following code in my base class for all Allure-supported tests:
[AllureNUnit]
internal abstract class PageTestBase : Microsoft.Playwright.NUnit.PageTest
{
protected async Task Step(string name, Func<Task> action)
{
try
{
await AllureApi.Step(name, action);
}
catch (Exception)
{
//save screenshot in case something goes wrong (mandatory)
await Page.ScreenshotAsync(new() { Path = "failure.png" });
//TODO: set result to failed
}
//TODO: depending on settings user can opt to save screenshots after every step
await Page.ScreenshotAsync(new() { Path = "AfterEachStep.png" });
}
}
I’d like to be able to create a step abstraction that allows to react after step finishes (i.e. take screenshot after failure and optionally take screenshot after every step). How can that be achieved in Allure.NUnit?
The solution that worked for me is to copy some code from Allure and customize it so that appropriate state machine is created:
public Task UiStep(string name, Func<Task> action) =>
ExecuteStepAsync(name, async () =>
{
await action();
return Task.FromResult<object?>(null);
});
/// <summary>
/// Executes the asynchronous function and reports the result as a new step
/// of the current fixture, test or step. Requires one of these contexts to
/// be active.
/// </summary>
/// <param name="name">The name of the step.</param>
/// <param name="function">The asynchronous function to run.</param>
/// <returns>The original value returned by the function.</returns>
public Task<T> UiStep<T>(string name, Func<Task<T>> function) => ExecuteStepAsync(name, function);
private async Task<T> ExecuteStepAsync<T>(string name, Func<Task<T>> action)
{
T result;
Exception? error = null;
ExtendedApi.StartStep(name);
try
{
result = await action();
await SaveScreenshot(Page, _reportingSettings.EveryStepScreenshots, name);
}
catch (Exception e)
{
error = e;
await SaveScreenshot(Page, _reportingSettings.FailureScreenshots, name);
throw;
}
finally
{
ExtendedApi.ResolveStep(error);
}
return result;
}