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

Feature/Cucumber Messages #233

Open
wants to merge 252 commits into
base: main
Choose a base branch
from
Open

Feature/Cucumber Messages #233

wants to merge 252 commits into from

Conversation

clrudolphi
Copy link
Contributor

@clrudolphi clrudolphi commented Aug 15, 2024

Adds support for creation of Cucumber Messages during the execution of Reqnroll generated tests.
See Cucumber Message for information about the output format.

🤔 What's changed?

Changes are in three main area:

  1. Feature Generation: during feature-file code-behind code generation, the Gherkin toolchain is used to create the first few Messages for the feature. Factory methods are generated for each of these message types. These are attached to the FeatureInfo object.
  2. Cucumber Message Publication: written as an embedded plugin, this component listens for Reqnroll ExecutionEvents and converts them, and their attached state, to Cucumber Messages. These are 'published' to one or more consumers.
  3. FileSinkPlugin: an embedded runtime plugin, this plugin registers with the Publishing component to receive the Messages as they are released by the Publisher and stored to a file.

Messages are strings serialized from the CucumberMessage Envelope format and stored one per line in an ".ndjson" result file.

Configuration support is added as a new section of the reqnroll.json configuration file. (Without interfering with the existing configuration schema and config reading mechanisms). Configuration settings can also be overridden by use of environment variables.

⚡️ What's your motivation?

To provide future compatibility with the broader Cucumber eco-system of tooling.
To provide the input to a future implementation of a Reqnroll replacement to LivingDocs.

🏷️ What kind of change is this?

  • ⚡ New feature (non-breaking change which adds new behaviour)

♻️ Anything particular you want feedback on?

Anything.

📋 Checklist:

  • I've changed the behaviour of the code
    • I have added/updated tests to cover my changes.
  • My change requires a change to the documentation.
    • I have updated the documentation accordingly.
  • Users should know about my change
    • I have added an entry to the "[vNext]" section of the CHANGELOG, linking to this pull request & included my GitHub handle to the release contributors list.

@clrudolphi clrudolphi requested a review from gasparnagy August 15, 2024 16:21
@clrudolphi
Copy link
Contributor Author

FYI, github Build is failing b/c one produced component (FileSinkPlugin) gets published only to my local Nuget store. It can then not be found by the build pipeline in github.

@clrudolphi clrudolphi added the enhancement New feature or request label Aug 17, 2024
@clrudolphi
Copy link
Contributor Author

clrudolphi commented Aug 19, 2024

First end-to-end working scenario is operational.
Needed out of a PR review:

  • Overall code structure
  • Patterns that have been used (good/bad) and patterns that should have been used
  • Thread-safety: is the level of thread awareness and approach to thread-safety appropriate and adequate?

Next:

  • Copy the Cucumber Compatibility Kit scenarios into an integration test suite and build out the structure to build, invoke, and confirm compliance.

@clrudolphi clrudolphi force-pushed the feature-CucumberMessages branch from 364e466 to 1f2f1e6 Compare September 4, 2024 18:30
@clrudolphi
Copy link
Contributor Author

Build is failing b/c I have a private build of Cucumber Messages nuget package. When the next release of that comes out, I will patch up the nuget references in this branch.

@clrudolphi clrudolphi self-assigned this Sep 16, 2024
@gasparnagy
Copy link
Contributor

Build is failing b/c I have a private build of Cucumber Messages nuget package. When the next release of that comes out, I will patch up the nuget references in this branch.

This is fine. We have feed https://www.myget.org/feed/Packages/reqnroll-unstable where we could publish interim releases (of dependencies as well) and I think this feed is added to the nuget sources, so the build would be able to resolve it though them. But I never tested this model yet.

…mber Messages Publisher and Broker to the initialization sequence provided by the Plugin architecture.
…est project. The File Sink is hooked in as a nuget package.

Next: exploratory debugging to confirm the event listeners are wired up correctly at Feature start time.
Need to figure out why trace logging also not working.
…check of whether it had been initialized (temp).

(Temp) - added Debugger.Launch to FileSinkPlugin to force launch of debugger.
…Publisher from the FileSinkPlugIn completely.
…the use of a BlockingCollection. Eliminated base class for Sinks. Eliminated use of Async for MessageSinks. Sinks have to ensure their own thread-safety and non-blocking behavior. May want to revisit that.
…ke Messages (meta, Source, GherkinDocument, and Pickles).
… information into Messages. First example is transforming StepBinding classes into messages of type StepDefinition.
…pport for CucumberMessages for that feature.
…ioState emit sequences of Envelopes for consumption by the Publisher.
…fter scenario completion so that we have full binding Match info available to create the TestCase message.
minimal and pending scenarios added.
… which I don't think apply to the .NET implementation.

Need to add support for images and documents as embedded resources to be added to generated test projects before attachments and hooks can be implemented and tested.
Not yet added infrastructure to compare output ndjon with expected.
Fails on undefined steps (but not specific to Hooks).
Made change to TestExecutionEngine to add Feature, Scenario, and Step context to the HookBinding events.
… count for the test case is incremented on the testCaseStarted message.

Added a Test Scenario for this, leveraging the xRetry.Reqnroll plugin from nuget. For this test, the test framework is switched from MSTest to XUnit.

Not yet fully compliant b/c xRetry doesn't behave properly when a step fails b/c it is UNDEFINED.
@Code-Grump
Copy link
Contributor

Code-Grump commented Jan 23, 2025

First of all, those are great finds. Good job on such thorough investigation.

Onto the problem itself: ideally, a good API design prevents invalid states, but in this instance, I would suggest we allow plug-ins to publish messages that would be considered invalid. We're treating Cucumber Messages as a mechanism for providing visibility of test execution and if the plugin causes invalid messages to be published, it's on the plugin to decide whether it's important to its users to be fully compatible with the spec. It may be completely compatible with the tools in use by the plugin users!

The alternative would be to fail, either loudly causing a runtime failure for a user of the retry plugin, or silently and make the whole problem really opaque. I don't believe either of those are desirable failure modes, as both cause issues for the end-user that either stop them running tests or give them mysteriously incomplete output.

@clrudolphi
Copy link
Contributor Author

clrudolphi commented Jan 24, 2025

we might be able to queue them up and only write them upon receipt of the AfterTestRun event (and take that opportunity to patch up 'willBeRetried' values for any test cases that were retried.)

An alternative that occurred to me is to create an Interface that retry plugins must implement that we would call upon during handling of ScenarioFinished event. The interface would allow the retry plugins the opportunity to tell us whether a failed test case would be retried. I would implement a Null implementation of this interface and register it in the global container. Retry plugins would implement the interface and replace the null impl with their own in the global container.

Thoughts? Too complicated?

EDIT: resolved - see comment below

Updated the configuration.md file.
Modified the constants file to make use of 'Directory' consistent across the configuration and constants.
…uired refactoring and duplication of the retry feature and expected results.
…o that actual Messages are sorted by PickleID of the test case(Scenario). This will ensure that Attempt counts are properly compared.
@clrudolphi
Copy link
Contributor Author

Merged in changes that provide for support of Retried test cases. These changes refactored how execution progress is tracked and accounts for retried scenarios. Message generation is deferred until the entire Feature is finished. This allows us to identify that a scenario has been executed multiple times and adjust the 'willBeRetried' flag on prior executions.
Added a test Scenario that uses the NUnitRetry plugin. (The xUnit.Retry plugin works, but does not validate as it re-executes scenarios containing undefined steps which the CCK does not allow. A test using xUnit.Retry exists but is commented out.)

TODO: Need proper ordering; instead of direct publish, these should go in to the Messages cache for sorting by timestamp.
TODO: Enhance Validator to support these message types.
…w Message types of TestHookStarted and Finished.

Enhanced the validation test code to support these two Message types when building cross-reference indexes.
@clrudolphi
Copy link
Contributor Author

Added support for two new Message types (TestRunHookStarted and Finished). These correspond to Reqnroll's Before/After TestRun and Before/After Feature hooks.
The test for these is in the Non-CCK Scenarios category for now, as Cucumber hasn't released a CCK scenario for these message types. Once these are official, will need to update the test to match the CCK.

@fredrikeriksson
Copy link

fredrikeriksson commented Feb 7, 2025

This has nothing to do with the PR work per se, but the only way I can help as is, is by showing my appreciation of your efforts! Keep on rockin'!! :) @clrudolphi @gasparnagy

…a test (that has derived from SystemTest).

Relocated all embedded resource files to the conventional location.
Moved the External Data Interop basic test's resources to the Samples directory to align them with the pattern.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants