Skip to content

Commit

Permalink
Fix not panicking on fail_on_skipped() with retries (#250, #249)
Browse files Browse the repository at this point in the history
- add `NotFound` variant to `event::StepError`
  • Loading branch information
ilslv authored Dec 7, 2022
1 parent f7d8fd2 commit a585e5a
Show file tree
Hide file tree
Showing 20 changed files with 437 additions and 133 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ All user visible changes to `cucumber` crate will be documented in this file. Th



## [0.18.0] · 2022-??-??
[0.18.0]: /../../tree/v0.18.0

[Diff](/../../compare/v0.17.0...v0.18.0) | [Milestone](/../../milestone/21)

### BC Breaks

- Added `NotFound` variant to `event::StepError`. ([#250])

### Fixed

- Not panicking on `fail_on_skipped()` with retries. ([#250], [#249])

[#249]: /../../issues/249
[#250]: /../../pull/250




## [0.17.0] · 2022-11-23
[0.17.0]: /../../tree/v0.17.0

Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ repository = "https://github.com/cucumber-rs/cucumber"
readme = "README.md"
categories = ["asynchronous", "development-tools::testing"]
keywords = ["cucumber", "testing", "bdd", "atdd", "async"]
include = ["/src/", "/tests/after_hook.rs", "/tests/fail_fast.rs", "/tests/json.rs", "/tests/junit.rs", "/tests/libtest.rs", "/tests/retry.rs", "/tests/wait.rs", "/LICENSE-*", "/README.md", "/CHANGELOG.md"]
include = ["/src/", "/tests/after_hook.rs", "/tests/fail_fast.rs", "/tests/json.rs", "/tests/junit.rs", "/tests/libtest.rs", "/tests/retry.rs", "/tests/retry_fail_on_skipped.rs", "/tests/wait.rs", "/LICENSE-*", "/README.md", "/CHANGELOG.md"]

[package.metadata.docs.rs]
all-features = true
Expand Down Expand Up @@ -105,6 +105,10 @@ harness = false
name = "retry"
harness = false

[[test]]
name = "retry_fail_on_skipped"
harness = false

[[test]]
name = "wait"
required-features = ["libtest"]
Expand Down
14 changes: 14 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// TODO: Only because of `derive_more` macros, try to remove on next
// `derive_more` upgrade.
#![allow(clippy::use_self)]

//! Key occurrences in a lifecycle of [Cucumber] execution.
//!
//! The top-level enum here is [`Cucumber`].
Expand Down Expand Up @@ -396,6 +400,16 @@ impl<World> Clone for Step<World> {
/// [`Step`]: gherkin::Step
#[derive(Clone, Debug, Display, Error, From)]
pub enum StepError {
/// [`Step`] doesn't match any [`Regex`].
///
/// It's emitted whenever a [`Step::Skipped`] event cannot be tolerated
/// (such as when [`fail_on_skipped()`] is used).
///
/// [`Regex`]: regex::Regex
/// [`fail_on_skipped()`]: crate::WriterExt::fail_on_skipped()
#[display(fmt = "Step doesn't match any function")]
NotFound,

/// [`Step`] matches multiple [`Regex`]es.
///
/// [`Regex`]: regex::Regex
Expand Down
1 change: 0 additions & 1 deletion src/runner/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,6 @@ struct Executor<W, Before, After> {
/// [`Step`]s [`Collection`].
///
/// [`Collection`]: step::Collection
/// [`Step`]: step::Step
collection: step::Collection<W>,

/// Function, executed on each [`Scenario`] before running all [`Step`]s,
Expand Down
14 changes: 12 additions & 2 deletions src/writer/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,12 @@ impl<Out: io::Write> Basic<Out> {
self.clear_last_lines_if_term_present()?;

let style = |s| {
if retries.filter(|r| r.left > 0).is_some() {
if retries
.filter(|r| {
r.left > 0 && !matches!(err, event::StepError::NotFound)
})
.is_some()
{
self.styles.bright().retry(s)
} else {
self.styles.err(s)
Expand Down Expand Up @@ -924,7 +929,12 @@ impl<Out: io::Write> Basic<Out> {
self.clear_last_lines_if_term_present()?;

let style = |s| {
if retries.filter(|r| r.left > 0).is_some() {
if retries
.filter(|r| {
r.left > 0 && !matches!(err, event::StepError::NotFound)
})
.is_some()
{
self.styles.bright().retry(s)
} else {
self.styles.err(s)
Expand Down
9 changes: 2 additions & 7 deletions src/writer/fail_on_skipped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,12 @@ where
) {
use event::{
Cucumber, Feature, RetryableScenario, Rule, Scenario, Step,
StepError::Panic,
StepError::NotFound,
};

let map_failed = |f: &Arc<_>, r: &Option<_>, sc: &Arc<_>| {
if (self.should_fail)(f, r.as_deref(), sc) {
Step::Failed(
None,
None,
None,
Panic(Arc::new("not allowed to skip")),
)
Step::Failed(None, None, None, NotFound)
} else {
Step::Skipped
}
Expand Down
6 changes: 2 additions & 4 deletions src/writer/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ impl<Out: io::Write> Json<Out> {
},
event::Step::Failed(_, loc, _, err) => {
let status = match &err {
event::StepError::NotFound => Status::Undefined,
event::StepError::AmbiguousMatch(..) => Status::Ambiguous,
event::StepError::Panic(..) => Status::Failed,
};
Expand Down Expand Up @@ -405,10 +406,7 @@ mod status {
/// [`event::StepError::AmbiguousMatch`].
Ambiguous,

/// Never constructed and is here only to fully describe
/// [JSON schema][1].
///
/// [1]: https://github.com/cucumber/cucumber-json-schema
/// [`event::Step::Failed`] with an [`event::StepError::NotFound`].
Undefined,

/// Never constructed and is here only to fully describe
Expand Down
7 changes: 6 additions & 1 deletion src/writer/libtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,12 @@ impl<W: Debug + World, Out: io::Write> Libtest<W, Out> {
}
}
Step::Failed(_, loc, world, err) => {
if retries.map(|r| r.left > 0).unwrap_or_default() {
if retries
.map(|r| {
r.left > 0 && !matches!(err, event::StepError::NotFound)
})
.unwrap_or_default()
{
self.retried += 1;
} else {
self.failed += 1;
Expand Down
9 changes: 7 additions & 2 deletions src/writer/summarize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,13 @@ impl<Writer> Summarize<Writer> {
.handled_scenarios
.insert((feature, rule, scenario), Skipped);
}
Step::Failed(..) => {
if retries.filter(|r| r.left > 0).is_some() {
Step::Failed(_, _, _, err) => {
if retries
.filter(|r| {
r.left > 0 && !matches!(err, event::StepError::NotFound)
})
.is_some()
{
self.steps.retried += 1;

let inserted_before = self
Expand Down
9 changes: 5 additions & 4 deletions tests/after_hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ async fn main() {

future::ready(()).boxed()
})
.fail_on_skipped()
.run_and_exit("tests/features/wait");

let err = AssertUnwindSafe(res)
Expand All @@ -59,12 +60,12 @@ async fn main() {
.expect_err("should err");
let err = err.downcast_ref::<String>().unwrap();

assert_eq!(err, "2 steps failed, 1 parsing error, 4 hook errors");
assert_eq!(err, "4 steps failed, 1 parsing error, 8 hook errors");
assert_eq!(NUMBER_OF_BEFORE_WORLDS.load(Ordering::SeqCst), 11);
assert_eq!(NUMBER_OF_AFTER_WORLDS.load(Ordering::SeqCst), 11);
assert_eq!(NUMBER_OF_FAILED_HOOKS.load(Ordering::SeqCst), 2);
assert_eq!(NUMBER_OF_PASSED_STEPS.load(Ordering::SeqCst), 6);
assert_eq!(NUMBER_OF_SKIPPED_STEPS.load(Ordering::SeqCst), 2);
assert_eq!(NUMBER_OF_FAILED_HOOKS.load(Ordering::SeqCst), 4);
assert_eq!(NUMBER_OF_PASSED_STEPS.load(Ordering::SeqCst), 4);
assert_eq!(NUMBER_OF_SKIPPED_STEPS.load(Ordering::SeqCst), 4);
assert_eq!(NUMBER_OF_FAILED_STEPS.load(Ordering::SeqCst), 2);
}

Expand Down
7 changes: 7 additions & 0 deletions tests/features/wait/nested/rule.feature
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ Feature: Basic
Then unknown
Then 1 sec

@allow.skipped
Scenario: 1 sec
Given 1 sec
When 1 sec
Then unknown
Then 1 sec

Rule: rule
@fail_before
Scenario: 2 secs
Expand Down
7 changes: 7 additions & 0 deletions tests/features/wait/rule.feature
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ Feature: Basic
Then unknown
Then 1 sec

@allow.skipped
Scenario: 1 sec
Given 1 sec
When 1 sec
Then unknown
Then 1 sec

Rule: rule
@fail_before
Scenario: 2 secs
Expand Down
1 change: 1 addition & 0 deletions tests/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ async fn main() {
.boxed_local()
})
.with_writer(writer::Json::new(file.reopen().unwrap()))
.fail_on_skipped()
.run("tests/features/wait")
.await,
);
Expand Down
Loading

0 comments on commit a585e5a

Please sign in to comment.