diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index 669e229b..00000000
--- a/.gitattributes
+++ /dev/null
@@ -1,22 +0,0 @@
-# Set default behaviour, in case users don't have core.autocrlf set.
-* text=crlf
-
-# Explicitly declare text files we want to always be normalized and converted
-# to native line endings on checkout.
-*.cs text
-*.txt text
-*.md text
-*.nuspec text
-*.config text
-*.snk text
-*.js text
-*.resx text
-*.css text
-*.sln text
-*.csproj text
-
-# Denote all files that are truly binary and should not be modified.
-*.exe binary
-*.dll binary
-
-*.approved.* binary
\ No newline at end of file
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
deleted file mode 100644
index 31d907a9..00000000
--- a/.github/CODEOWNERS
+++ /dev/null
@@ -1 +0,0 @@
-* @SonOfSardaar @MehdiK
\ No newline at end of file
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
deleted file mode 100644
index a0d641e9..00000000
--- a/.github/workflows/build.yml
+++ /dev/null
@@ -1,286 +0,0 @@
-name: Build and Test
-on:
- push:
- pull_request:
- workflow_dispatch:
- inputs:
- runPublish:
- description: 'Publish Nuget ?'
- required: true
- default: false
- type: boolean
-
- publishWhichNuget:
- description: 'Which Nuget ?'
- required: true
- default: 'Only Changed'
- type: choice
- options:
- - Only Changed
- - All
-
-jobs:
- build:
- runs-on: ubuntu-latest
- outputs:
- semver: ${{ steps.gitversion.outputs.semVer }}
- fullsemver: ${{ steps.gitversion.outputs.fullSemVer }}
- nugetversion: ${{ steps.gitversion.outputs.fullSemVer }}
- publishNuget: ${{ steps.changes.outputs.BddfyUpdated == 'true' || steps.changes.outputs.SamplesUpdated == 'true' || github.event.inputs.publishWhichNuget == 'All' }}
- steps:
- - name: Checkout code
- uses: actions/checkout@v5
- with:
- fetch-depth: 0 # Required for GitVersion
-
- - name: Install GitVersion
- uses: gittools/actions/gitversion/setup@v4.1.0
- with:
- versionSpec: '6.x'
-
- - name: Determine Version
- uses: gittools/actions/gitversion/execute@v4.1.0
- id: gitversion
-
- - name: Format NuGet version
- run: |
- buildNumber="${{steps.gitversion.outputs.preReleaseNumber}}${{ steps.gitversion.outputs.buildMetaData }}"
-
- if [[ "${GITHUB_REF}" != "refs/heads/${{ github.event.repository.default_branch }}" ]]; then
- buildNumber="${buildNumber}-beta"
- fi
-
- packageVersion="${{ steps.gitversion.outputs.majorMinorPatch }}.${buildNumber}"
- echo "packageVersion=$packageVersion" >> $GITHUB_OUTPUT
- id: formatversion
-
- - name: Display GitVersion outputs
- run: |
- echo "Version: ${{ steps.gitversion.outputs.semVer }}"
- echo "AssemblyVersion: ${{ steps.gitversion.outputs.assemblySemVer }}"
- echo "FileVersion: ${{ steps.gitversion.outputs.assemblySemFileVer }}"
- echo "NuGet Version: ${{ steps.gitversion.outputs.fullSemVer }}"
- echo "Package Version: ${{ steps.formatversion.outputs.packageVersion }}"
-
- - name: Setup .NET
- uses: actions/setup-dotnet@v5
- with:
- dotnet-version: '8.0.x'
-
- - name: Build project
- working-directory: src
- run: >-
- dotnet build --configuration Release
- /p:Version=${{ steps.gitversion.outputs.assemblySemVer }}
- /p:AssemblyVersion=${{ steps.gitversion.outputs.assemblySemVer }}
- /p:FileVersion=${{ steps.gitversion.outputs.assemblySemFileVer }}
- /p:PackageVersion=${{ steps.formatversion.outputs.packageVersion }}
-
- - name: Run tests with coverage
- working-directory: src
- env:
- DiffEngine_Disabled: 'true'
- run: >-
- dotnet test
- --configuration Release
- --collect:"XPlat Code Coverage"
- --results-directory ../coverage
-
- - name: Generate coverage report
- uses: danielpalme/ReportGenerator-GitHub-Action@5.4.16
- with:
- reports: 'coverage/**/coverage.cobertura.xml'
- targetdir: 'coverage-report'
- reporttypes: 'Html;Cobertura;TextSummary'
-
- - name: Display Code Coverage Summary
- run: |
- echo "## š Code Coverage Summary" >> $GITHUB_STEP_SUMMARY
- if [ -f "coverage-report/Summary.txt" ]; then
- echo '```' >> $GITHUB_STEP_SUMMARY
- cat coverage-report/Summary.txt >> $GITHUB_STEP_SUMMARY
- echo '```' >> $GITHUB_STEP_SUMMARY
- echo "### Build Log Coverage Summary:"
- cat coverage-report/Summary.txt
- else
- echo "ā ļø Coverage summary file not found"
- echo "ā ļø Coverage summary file not found" >> $GITHUB_STEP_SUMMARY
- fi
-
- - name: Generate Rich Release Notes
- id: release_notes
- uses: mikepenz/release-changelog-builder-action@v5.4.1
- with:
- configuration: |
- {
- "template": "## š Release ${{ steps.gitversion.outputs.semVer }}\n\n### š Release Information\n- **Version**: ${{ steps.gitversion.outputs.semVer }}\n- **NuGet Version**: ${{ steps.gitversion.outputs.fullSemVer }}\n- **Build Date**: $(date -u +'%Y-%m-%d %H:%M:%S UTC')\n- **Commit**: ${{ github.sha }}\n\n#{{CHANGELOG}}\n\n### š Statistics\n- **Total Changes**: #{{UNCATEGORIZED_COUNT}} commits\n- **Contributors**: #{{CONTRIBUTORS}}\n\n---\n*Generated automatically by GitHub Actions*",
- "categories": [
- {
- "title": "## š Features",
- "labels": ["feature", "enhancement", "feat"]
- },
- {
- "title": "## š Bug Fixes",
- "labels": ["bug", "fix", "bugfix"]
- },
- {
- "title": "## š Documentation",
- "labels": ["documentation", "docs"]
- },
- {
- "title": "## š§ Maintenance",
- "labels": ["maintenance", "chore", "refactor"]
- },
- {
- "title": "## ā ļø Breaking Changes",
- "labels": ["breaking", "breaking-change"]
- }
- ],
- "pr_template": "- #{{TITLE}} (#{{NUMBER}}) by @#{{AUTHOR}}",
- "empty_template": "- #{{TITLE}} (#{{HASH}}) by @#{{AUTHOR}}",
- "max_pull_requests": 200,
- "max_back_track_time_days": 365
- }
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Save Release Notes to File
- run: echo "${{ steps.release_notes.outputs.changelog }}" > release-notes.md
-
- - name: Upload Release Notes as artifact
- uses: actions/upload-artifact@v4
- with:
- name: release-notes
- path: release-notes.md
-
- - name: Check for changes in project paths
- id: changes
- run: |
- latestTag=$(git describe --tags --abbrev=0)
-
- if git diff --quiet "$latestTag" HEAD -- src/Samples/; then
- echo "SamplesUpdated=false" >> $GITHUB_OUTPUT
- else
- echo "SamplesUpdated=true" >> $GITHUB_OUTPUT
- fi
-
- if git diff --quiet "$latestTag" HEAD -- src/TestStack.BDDfy/; then
- echo "BddfyUpdated=false" >> $GITHUB_OUTPUT
- else
- echo "BddfyUpdated=true" >> $GITHUB_OUTPUT
- fi
-
- - name: Print changed paths
- run: |
- echo "SamplesUpdated: ${{ steps.changes.outputs.SamplesUpdated }}"
- echo "BddfyUpdated: ${{ steps.changes.outputs.BddfyUpdated }}"
-
- - name: Create Samples package
- working-directory: src
- if: steps.changes.outputs.SamplesUpdated == 'true' || github.event.inputs.publishWhichNuget == 'All'
- run: >-
- dotnet pack ./Samples/TestStack.BDDfy.Samples/*.csproj
- --configuration Release
- --no-build
- /p:PackageVersion=${{ steps.formatversion.outputs.packageVersion }}
- --output ../packages
-
- - name: Create Bddfy package
- working-directory: src
- if: steps.changes.outputs.BddfyUpdated == 'true' || github.event.inputs.publishWhichNuget == 'All'
- run: >-
- dotnet pack ./TestStack.BDDfy/*.csproj
- --configuration Release
- --no-build
- /p:PackageVersion=${{ steps.formatversion.outputs.packageVersion }}
- --output ../packages
-
- - name: Upload NuGet package as artifact
- uses: actions/upload-artifact@v4
- with:
- name: nuget-package
- path: packages/*.nupkg
-
- - name: Publish coverage report as artifact
- uses: actions/upload-artifact@v4
- with:
- name: coverage-report
- path: coverage-report/
-
- publish-nuget:
- runs-on: ubuntu-latest
- needs: build
- if: needs.build.outputs.publishNuget == 'true' && (github.event.inputs.runPublish == 'true' || github.ref_name == github.event.repository.default_branch)
- environment:
- name: Publish
- url: https://www.nuget.org/packages/TestStack.BDDfy/
-
- steps:
- - name: Download NuGet package
- uses: actions/download-artifact@v5
- with:
- name: nuget-package
- path: packages
-
- - name: Setup .NET
- uses: actions/setup-dotnet@v5
- with:
- dotnet-version: '8.0.x'
-
- - name: Publish to NuGet
- run: dotnet nuget push packages/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
-
- create-release-tag:
- runs-on: ubuntu-latest
- needs: [build, publish-nuget]
- if: github.event.inputs.runPublish == 'true' && github.ref_name == github.event.repository.default_branch
- permissions:
- contents: write
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v5
- with:
- fetch-depth: 0
- token: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Check if tag already exists
- id: check_tag
- run: |
- TAG="v${{ needs.build.outputs.semver }}"
- if git rev-parse "$TAG" >/dev/null 2>&1; then
- echo "Tag $TAG already exists"
- echo "tag_exists=true" >> $GITHUB_OUTPUT
- else
- echo "Creating new tag: $TAG"
- echo "tag_exists=false" >> $GITHUB_OUTPUT
- echo "new_tag=$TAG" >> $GITHUB_OUTPUT
- fi
-
- - name: Download Release Notes
- if: steps.check_tag.outputs.tag_exists == 'false'
- uses: actions/download-artifact@v5
- with:
- name: release-notes
- path: .
-
- - name: Create Git Tag and GitHub Release
- if: steps.check_tag.outputs.tag_exists == 'false'
- run: |
- TAG="${{ steps.check_tag.outputs.new_tag }}"
-
- # Configure git
- git config user.name "github-actions[bot]"
- git config user.email "github-actions[bot]@users.noreply.github.com"
-
- # Create and push tag
- git tag -a "$TAG" -m "Release $TAG"
- git push origin "$TAG"
-
- # Create GitHub release
- gh release create "$TAG" \
- --title "Release $TAG" \
- --notes-file release-notes.md \
- --generate-notes
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index ad4aa3cb..00000000
--- a/.gitignore
+++ /dev/null
@@ -1,32 +0,0 @@
-_ReSharper.*
-bin/
-obj/
-*.user
-*.suo
-*~
-*.swp
-*.orig
-*.nupkg
-*.received.txt
-*.crunchproject.local.xml
-*.crunchsolution.local.xml
-*.cache
-*.userprefs
-.DS_Store
-packages/*
-PackageBuild/*
-Build/*
-TestResult.xml
-TestStack.BDDfy.sln.ide/graph
-_NCrunch_TestStack.BDDfy/
-TestStack.BDDfy.sln.ide/
-src/packages/
-src/.vs/
-.vs/
-project.lock.json
-tools/Cake/
-tools/GitReleaseNotes/
-tools/gitversion.commandline/
-artifacts/
-*.code-workspace
-**/coverage
diff --git a/GitVersion.yml b/GitVersion.yml
deleted file mode 100644
index 29e4741b..00000000
--- a/GitVersion.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-mode: ContinuousDelivery
-next-version: 8.0.0
-branches:
- main:
- increment: Patch
- regex: ^main$
- is-release-branch: true
-ignore:
- sha: []
diff --git a/docs/Customizing/ArchitectureOverview.md b/docs/Customizing/ArchitectureOverview.md
deleted file mode 100644
index 17817557..00000000
--- a/docs/Customizing/ArchitectureOverview.md
+++ /dev/null
@@ -1,100 +0,0 @@
-# Architecture Overview
-## Introduction ##
-This post provides an overview of the main components of the BDDfy architecture to provide some context for the rest of this section and to illustrate the extensibility points.
-
-
-
-The unit of operation in BDDfy is the Story. A Story has metadata (information about the Story) and a collection of Scenarios. Each Scenario represents a test class and contains metadata and a collection of Execution Steps, which are the methods on the test class. There are three types of architectural components in BDDfy: Scanners, Processors and Batch Processors. For each test class BDDfy composes a Story unit with various Scanners and passes it to the Processors in a processor pipeline. Once all of the test classes have been scanned and processed the Batch Processors run aggregate operations against all of the Stories.
-
-Scanners turn a call to BDDfy (from a method) into a Scenario which could potentially be related to a Story. BDDfy doesn't need Stories but if there is one it uses it. If a Scenario is not related to a Story then it is associated with a dummy placeholder. Each Story is then passed to the Processors, which perform various operations, including executing the tests, and populate the Stories, Scenarios and Steps with the test execution results. Once all of the tests have been scanned and processed, the Batch Processors take the collection of Stories and process their results. This could be any sort of aggregate operation, but currently all the batch processors are reports.
-
-## Scanners ##
-Most of the BDDfy in Action series so far has covered the various Scanners, so I wonāt go into much detail here. Suffice to say, BDDfy uses Scanners to scan each test class to find all of the methods on it and turn the test class into a Scenario. The different Scanners are shown here:
-
-
-
-### Story Scanner ###
-BDDfy creates a Story Scanner for each test object. This is the Scanner that actually scans the test object and turns it into a Story. It composes together the Story Metadata Scanner and the appropriate Scenario Scanner ā [Fluent](/BDDfy/Usage/FluentAPI.html) or [Reflective](/BDDfy/Usage/MethodNameConventions.html).
-
-The Story Metadata Scanner gets information from the Story attribute, if one exists on the class.
-
-A **Story** has the following properties:
-
-- **Story Metadata**: Information about the Story such as Title, As a, I want, So that
-- **Scenarios**: The collection of Scenarios related to the Story
-- **Result**: A Storyās Result is a Step Execution Result and is determined by the highest Step Execution Result of its Scenarios.
-- **Category**: The Story Category
-
-**Step Execution Results** have a numerical hierarchy and can be (in ascending order):
-
-- Not Executed (0)
-- Passed (1)
-- Not Implemented (2)
-- Inconclusive (3)
-- Failed (4)
-
-The Test Runner Processor assigns a numerical Step Execution Result to every Execution Step. The result of a Scenario is then determined by the highest value of from its Steps and the result of a Story is determined by the highest result of its Scenarios. For example, if a Step fails, then its parent Scenario and Story will also have a result of Failed.
-
-### Scenario Scanners ###
-Scenario Scanners scan the test class and use the information they find to create a Scenario. There is a Fluent Scenario Scanner and a Reflective Scenario Scanner.
-
-A **Scenario** has the following properties:
-
-- **Title**: The Scenario Title
-- **Steps**: The collection of Steps (test class methods) related to the Scenario
-- **Result**: A Scenarioās Result is a Step Execution Result and is determined by the highest Step Execution Result of its Steps.
-- **Duration**: How long the Scenario took to execute. Used by Diagnostics.
-
-### Step Scanners ###
-Step Scanners turn methods into Execution Steps. The Reflective Scanners (the Executable Attribute Step Scanner and the Method Name Scanner) scan the test class to find all the methods on it and turns them into Execution Steps. The Fluent Step Scanner is only a registry and in practice doesn't do any scanning.
-
-An **Execution Step** has the following properties:
-
-- **Title**: The Step Title
-- **Result**: The result of executing the Step.
-- **Duration**: How long the Step took to execute. Used by Diagnostics.
-- **Asserts**: Whether or not the Step is an Assertion Step.
-- **Should Report**: Whether the Step should be displayed in reports.
-- **Execution Order**: The order that the step should run in relative to the other steps. Can be (in ascending order)
- - Initialize (for example, "Context", "Setup)
- - Setup State ("Given")
- - Consecutive Setup State ("And Given")
- - Transition ("When)
- - Consecutive Transition "And When")
- - Assertion ("Then")
- - Consecutive Assertion ("And Then")
- - Tear Down ("TearDown")
-ā
-## Processors ##
-Once a test class has been scanned into a Story, the Story is passed into a **Processor pipeline** where a series of processing steps are performed on it. The Processors are categorized by Type and the order they run in is determined by this Type.
-
-The various **Process Types**, in order, are:
-
-1. Firstly
-1. Execute
-1. Before Report
-1. Report
-1. After Report
-1. Process Exceptions
-1. Finally
-
-
-
-
-1. **Test Runner (Execute)**: Executes the tests.
-1. **Console Reporter (Report)**: Displays the test result in the console.
-1. **Exception Processor (Process Exceptions)**: Handles exceptions.
-1. **Story Cache (Finally)**: Saves each Story for later processing by the Batch Processors.
-1. **Disposer (Finally)**: Cleans up the Story and its Scenarios.
-
-## Batch Processors ##
-Once all of the tests have been scanned and processed, the Batch Processors take all of the Stories and process their results (technically speaking they run in the [AppDomain DomainUnload event](http://msdn.microsoft.com/en-GB/library/system.appdomain.domainunload.aspx)). This could be any sort of result processing, but currently all the batch processors are reports. The built-in Batch Processors are displayed in the diagram below.
-
-
-
-- **HTML Reporter**: Creates the HTML report
-- **Markdown Reporter**: Creates the Markdown report
-- **Diagnostics Reporter**: Creates the Diagnostics report
-
-## Configurator ##
-The static Configurator class allows you to configure Scanners, Processors and Batch Processors. It lets you enable, disable, or replace individual components and it also allows you to add custom implementations.
diff --git a/docs/Customizing/CustomizingReports.md b/docs/Customizing/CustomizingReports.md
deleted file mode 100644
index 559d177a..00000000
--- a/docs/Customizing/CustomizingReports.md
+++ /dev/null
@@ -1,175 +0,0 @@
-# Customizing Reports
-This post looks at how to customize the HTML Report and how to create your own custom reports. You can customize the HTML report via configuration or by applying custom CSS or JavaScript. You can create custom reports either by implementing a new Processor or Batch Processor and adding them into their respective pipelines (see the [Architecture Overview](/BDDfy/Customizing/ArchitectureOverview.html) for details about the differences between these).
-
-## Customizing the HTML Report ##
-The HTML report is the most sophisticated report in [BDDfy](http://teststack.github.io/pages/BDDfy.html) and therefore provides a lot more things that you can configure. Its configuration is defined by the IHtmlReportConfiguration interface.
-
- public interface IHtmlReportConfiguration
- {
- string ReportHeader { get; }
- string ReportDescription { get; }
- string OutputPath { get; }
- string OutputFileName { get; }
- bool RunsOn(Story story);
- }
-
-You can create a new configuration by implementing that interface or you can inherit from the DefaultHtmlReportConfiguration class, used to configure the standard HTML Report, and just override specific properties. Here is an example of a custom configuration, taken from the ATM sample, available on github [here](https://github.com/TestStack/TestStack.BDDfy/tree/master/TestStack.BDDfy.Samples/Atm).
-
- public class HtmlReportConfig : DefaultHtmlReportConfiguration
- {
- public override bool RunsOn(Core.Story story)
- {
- return story.MetaData.Type.Namespace != null && story.MetaData.Type.Namespace.EndsWith("Atm");
- }
-
- ///
- /// Change the output file name
- ///
- public override string OutputFileName
- {
- get
- {
- return "ATM.html";
- }
- }
-
- ///
- /// Change the report header to your project
- ///
- public override string ReportHeader
- {
- get
- {
- return "ATM Solutions";
- }
- }
-
- ///
- /// Change the report description
- ///
- public override string ReportDescription
- {
- get
- {
- return "A reliable solution for your offline banking needs";
- }
- }
- }
-
-which produces the following customised report, which you will find in your bin directory named ATM.html:
-
-
-
-
-The HTML report is a [Batch Processor](/BDDfy/Customizing/ArchitectureOverview.html) and is implemented by the HtmlReporter class. To plug the new report into BDDfy you need to create a new HtmlReporter and pass the custom configuration into its constructor. As I explained in the [Reports post](/BDDfy/Usage/Reports.html), the place to apply that configuration to BDDfy is the Configurator class, which is called before the tests run.
-
- Configurator.BatchProcessors.Add(new HtmlReporter(new HtmlReportConfig()));
-
-The use of the Add method means this is adding a second HTML Report processor into the Batch Processor pipeline, so the default report runner will still run. If you actually want the new report to replace the default report, then you will also need to disable the default report.
-
- Configurator.BatchProcessors.HtmlReport.Disable();
-
-## Custom CSS and JavaScript ##
-You can customize a lot more about the HTML report. BDDfy uses the BDDfy.css file to style the report and BDDfy.js and jQuery to add interactivity to it. You will find these files in the bin directory alongside the HTML report. You can customise the styles by adding a bddifyCustom.css class and the behaviour by adding a bddifyCustom.js file. These files also need to be in the same directory as the HTML report file. This will affect all the reports in the project.
-
-
-## Create a custom report by creating a new Processor ##
-One way to create a custom report is to implement a new Processor and plug it into the Processor pipeline. You just have to implement the one Process() method and set the Process Type to Report.
-
-An example of doing this is provided in the BDDfy Tic Tac Toe sample project with the Custom Text Reporter. The sample is available on [github](https://github.com/TestStack/TestStack.BDDfy/tree/master/TestStack.BDDfy.Samples) or [nuget](http://nuget.org/packages/TestStack.BDDfy.Samples/).
-
- ///
- /// This is a custom reporter that shows you how easily you can create a custom report.
- /// Just implement IProcessor and you are done
- ///
- public class CustomTextReporter : IProcessor
- {
- private static readonly string Path;
-
- private static string OutputDirectory
- {
- get
- {
- string codeBase = typeof(CustomTextReporter).Assembly.CodeBase;
- var uri = new UriBuilder(codeBase);
- string path = Uri.UnescapeDataString(uri.Path);
- return System.IO.Path.GetDirectoryName(path);
- }
- }
-
- static CustomTextReporter()
- {
- Path = System.IO.Path.Combine(OutputDirectory, "BDDfy-text-report.txt");
-
- if(File.Exists(Path))
- File.Delete(Path);
-
- var header =
- " A custom report created from your test assembly with no required configuration " +
- Environment.NewLine +
- Environment.NewLine +
- Environment.NewLine +
- Environment.NewLine;
- File.AppendAllText(Path, header);
- }
-
- public void Process(Story story)
- {
- // use this report only for tic tac toe stories
- if (!story.MetaData.Type.Name.Contains("TicTacToe"))
- return;
-
- var scenario = story.Scenarios.First();
- var scenarioReport = new StringBuilder();
- scenarioReport.AppendLine(string.Format(" SCENARIO: {0} ", scenario.Title));
-
- if (scenario.Result != StepExecutionResult.Passed && scenario.Steps.Any(s => s.Exception != null))
- {
- scenarioReport.Append(string.Format(" {0} : ", scenario.Result));
- scenarioReport.AppendLine(scenario.Steps.First(s => s.Result == scenario.Result).Exception.Message);
- }
-
- scenarioReport.AppendLine();
-
- foreach (var step in scenario.Steps)
- scenarioReport.AppendLine(string.Format(" [{1}] {0}", step.StepTitle, step.Result));
-
- scenarioReport.AppendLine("--------------------------------------------------------------------------------");
- scenarioReport.AppendLine();
-
- File.AppendAllText(Path, scenarioReport.ToString());
- }
-
- public ProcessType ProcessType
- {
- get { return ProcessType.Report; }
- }
- }
-
-This produces the BDDfy-text-report.txt text file report which is output to the bin directory:
-
-
-
-## Create a custom report by creating a new Batch Processor ##
-While that is one way that you can create a custom report, probably the better way to do it is to implement a new Batch Processor. The Processor runs as each test is being executed and allows you to build up the report, whereas a Batch Processor has the advantage of running after all of the tests have finished, meaning that you have access to total and summary information, such as diagnostics.
-
-As an example of creating a custom report by creating a new Batch Processor, I was recently messing around with running tests in parallel and, as you might expect, the normal console report was quite jumbled. Multiple console report Processors were writing to the console at the same time and different test results were overlapping. The solution was to run the console report after all of the tests had run by creating a new Console Reporter as a Batch Processor rather than a Processor.
-
- public class MyConsoleReporter : IBatchProcessor
- {
- public void Process(IEnumerable stories)
- {
- var reporter = new ConsoleReporter();
- stories
- .ToList()
- .ForEach(story => reporter.Process(story));
- }
- }
-
-Then I just needed to add it to the Batch Processor pipeline and disable the built-in console report:
-
- Configurator.Processors.ConsoleReport.Disable();
- Configurator.BatchProcessors.Add(new MyConsoleReporter());
-
-
-That's a bit of a hack for demo purposes. The HTML, MarkDown, and Diagnostics reports are all implemented as Batch Processors and I would recommend checking them out for examples of how to create a new report.
diff --git a/docs/Customizing/ExampleCustomFramework.md b/docs/Customizing/ExampleCustomFramework.md
deleted file mode 100644
index 86018822..00000000
--- a/docs/Customizing/ExampleCustomFramework.md
+++ /dev/null
@@ -1,390 +0,0 @@
-# Example - Creating a custom framework
-## Introduction ##
-This post provides some sample code to demonstrate some of the BDDfy extension points, and to provide a reference point for some of your own customizations. In this example we modify BDDfy to work as a context specification framework, similar to [mspec](https://github.com/machine/machine.specifications).
-
-So, the requirements for this hypothetical custom framework are
-
-- It should use the context specification grammar (Establish Context, Because Of, It Should) rather than the Given When Then grammar that BDDfy uses by default
-- It should have a Class per Scenario style, like the [Testcase class per Fixture](http://xunitpatterns.com/Testcase%20Class%20per%20Fixture.html) pattern from Gerard Meszarosā [XUnit Test Patterns](http://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054/ref=sr_1_1?s=books&ie=UTF8&qid=1368296304&sr=1-1&keywords=xunit+test+patterns) book (a book which I highly recommend).
-- It should not require any testing framework, such as NUnit or MsTest. In fact, the only dependency will be BDDfy.
-- It should not require a test runner, such as TestDriven.Net or ReSharper
-- Iām not a fan of attributes, so no attributes for the BDDfy Story, the test fixture or for the test methods
-- The HTML report should be customised for my new framework. (Letās call it Context Specifier).
-- Finally, I would like to be able to run tests sequentially or in parallel
-
-## ContextSpecification Base Class ##
-
-I am going to start off with a base class to establish the context specification method template. Iāll also put a Story property here as an alternative to the Story attribute so that each specification can specify the Story that they belong to. BDDfy does not require Scenarios to have a Story, but itās a convention Iām wanting to enforce for this framework! The Run method is what calls BDDfy to run the test. By default it will call BDDfy() and BDDfy will convert the class name into the scenario title. If I want to override that value I just need to set the ScenarioTitle in the class constructor and then it will be used with the BDDfy(scenarioTitle) overload.
-
-This is actually the only time that BDDfy is called in this framework and the whole test suite. It is very DRY and I much prefer it to adding fixture and test attributes for every test. (By the way, even if I were using a framework like nunit/xunit this base class would still be the only place I would need to use their attributes or call BDDfy. Their runners are smart enough to find the test classes, which is a nice benefit of using inheritance in this sort of framework).
-
- public abstract class ContextSpecification
- {
- protected virtual void EstablishContext() { }
- protected virtual void BecauseOf() { }
-
- public abstract UserStory Story { get; }
-
- public virtual string ScenarioTitle { get; set; }
-
- public void Run()
- {
- if (string.IsNullOrEmpty(ScenarioTitle))
- {
- this.BDDfy();
- }
- else
- {
- this.BDDfy(ScenarioTitle);
- }
- }
- }
-
-With this base class in place I can write a class for each scenario. To do that, Iām going to modify the BDDfy ATM samples. The Context Specification style utilises the same four-phase test pattern as Arrange Act Assert or Given When Then, setting up the pre-conditions for the test in the Establish Context phase, exercising the system under test (SUT) in the Because Of phase, and then verifying expectations in the It Should phase.
-
-The user story is associated with the specification by setting the Story property to a new instance of a UserStory class - in this case the AtmWithdrawCashStory class. Notice that I am able to override the scenario title in the constructor, so the report will read "When account funds are less than zero" rather than "When account has insufficient funds" which BDDfy would derive from the class name.
-
- public class WhenAccountHasInsufficientFunds : ContextSpecification
- {
- private Card _card;
- private Atm _atm;
-
- public WhenAccountHasInsufficientFunds()
- {
- ScenarioTitle = "When account funds are less than zero";
- }
-
- protected override void EstablishContext()
- {
- _card = new Card(true, 10);
- _atm = new Atm(100);
- }
-
- protected override void BecauseOf()
- {
- _atm.RequestMoney(_card, 20);
- }
-
- public override UserStory Story
- {
- get { return new AtmWithdrawCashStory(); }
- }
-
- void ItShouldNotDispenseAnyMoney()
- {
- Assert.AreEqual(0, _atm.DispenseValue);
- }
-
- void AndItShouldSayThereAreInsufficientFunds()
- {
- Assert.AreEqual(DisplayMessage.InsufficientFunds, _atm.Message);
- }
-
- void AndItShouldHaveTheSameAccountBalance()
- {
- Assert.AreEqual(10, _card.AccountBalance);
- }
-
- void AndItShouldReturnTheCard()
- {
- Assert.IsFalse(_atm.CardIsRetained);
- }
- }
-
-## The Context Specification Grammar ##
-
-To use my new grammar instead of the default BDDfy Given When Then grammar I need to tell BDDfy how to find step methods on the class, which I can do by replacing the BDDfy DefaultMethodNameStepScanner with a new MethodNameStepScanner. BDDfy defines the Given When Then grammar in the DefaultMethodNameStepScanner and the easiest way to create a new scanner is to copy and modify that.
-
- public class ContextSpecificationStepScanner : MethodNameStepScanner
- {
- public ContextSpecificationStepScanner()
- : base(
- CleanupTheStepText,
- new[]
- {
- new MethodNameMatcher(s => s.StartsWith("EstablishContext", StringComparison.OrdinalIgnoreCase), false, ExecutionOrder.SetupState, false),
- new MethodNameMatcher(s => s.StartsWith("BecauseOf", StringComparison.OrdinalIgnoreCase), false, ExecutionOrder.Transition, false),
- new MethodNameMatcher(s => s.StartsWith("It", StringComparison.OrdinalIgnoreCase), true, ExecutionOrder.Assertion, true),
- new MethodNameMatcher(s => s.StartsWith("AndIt", StringComparison.OrdinalIgnoreCase), true, ExecutionOrder.ConsecutiveAssertion, true)
- })
- {
- }
-
- static string CleanupTheStepText(string stepText)
- {
- if (stepText.StartsWith("EstablishContext", StringComparison.OrdinalIgnoreCase))
- return "Establish context ";
-
- if (stepText.StartsWith("BecauseOf", StringComparison.OrdinalIgnoreCase))
- return "Because of ";
-
- if (stepText.StartsWith("AndIt ", StringComparison.OrdinalIgnoreCase))
- return stepText.Remove("and".Length, "It".Length);
-
- return stepText;
- }
- }
-
-The custom scanner requires two parameters in the constructor; a step text transformer and an array of MethodNameMatchers. Each MethodNameMatcher defines a predicate to identify if the method matches, whether or not the method is an assertion, the type of method it is, and whether it should be displayed on the report. With Given When Then steps you want to display all of the steps on the report. With my context specification grammar I just want to display the name of the class and the assertions, so I specify false for the shouldReport parameter of the āEstablishContextā and āBecauseOfā steps so that they wonāt display on the report. This is not something we recommend, as it would be helpful to receive error messages for those steps if they fail, but it makes sense for reporting purposes with this grammar as repeating EstablishContext and BecauseOf would not be much use on the report (and a reason why Given When Then grammar is preferable to this one).
-
-Once I have my new grammar I need to tell BDDfy to use it by using the Configurator to disable the default scanner and to add the new one:
-
- Configurator.Scanners.DefaultMethodNameStepScanner.Disable();
- Configurator.Scanners.Add(() => new ContextSpecificationStepScanner());
-
-## Replacing the BDDfy Story Attribute ##
-
-The next thing on my list is the Story. BDDfy uses an attribute on the test class to specify the Story that the Scenario test class belongs to. You are not limited to this though, and like most things in BDDfy, you are able to customise this behaviour if you want. Iām going to create a simple UserStory class that stores Story metadata. It is just a standard class that does not implement any BDDfy behaviours. I could potentially just use the BDDfy StoryMetaData class directly, but I will keep things separate for now.
-
- public abstract class UserStory
- {
- public string Title { get; set; }
- public string AsA { get; set; }
- public string IWant { get; set; }
- public string SoThat { get; set; }
- }
-
-
-To create a new story class, I just have to inherit from the UserStory class and set the metadata properties in its constructor. Here is the AtmWithdrawCashStory from the example above.
-
- public class AtmWithdrawCashStory : UserStory
- {
- public AtmWithdrawCashStory()
- {
- Title = "Withdrawing cash from the ATM";
- AsA = "As an Account Holder";
- IWant = "I want to withdraw cash from an ATM";
- SoThat = "So that I can get money when the bank is closed";
- }
- }
-
-To tell BDDfy how to find these Stories and match them to the appropriate Scenario, I need to implement a new Story Metadata Scanner to associate the Scenario test class with its Story.
-
- public class StoryMetaDataScanner : IStoryMetaDataScanner
- {
- public StoryMetaData Scan(object testObject, Type explicitStoryType = null)
- {
- var specification = testObject as ContextSpecification;
- if (specification == null)
- return null;
-
- var story = specification.Story;
-
- return new StoryMetaData(story.GetType(), story.AsA, story.IWant, story.SoThat, story.Title);
- }
- }
-
-My convention of having all my test classes inherit from the base ContextSpecifcation comes in handy here as it enables me to easily get access to the Story property and use it to create the StoryMetaData that BDDfy needs. Now, I can just replace the BDDfy StoryMetaDataScanner with my custom one using the Configurator.
-
- Configurator.Scanners.StoryMetaDataScanner = () => new StoryMetaDataScanner();
-
-## Customizing the HTML Report ##
-
-I want to change the HTML report to have the name and description of the framework and to change the name of the html file that is generated. You can do this by inheriting from the DefaultHtmlReportConfiguration class.
-
- public class CustomHtmlReportConfiguration : DefaultHtmlReportConfiguration
- {
- public override string ReportHeader
- {
- get
- {
- return "Context Specifier";
- }
- }
-
- public override string ReportDescription
- {
- get
- {
- return "A simple context specification framework for .Net developers";
- }
- }
-
- public override string OutputFileName
- {
- get
- {
- return "ContextSpecifications.html";
- }
- }
- }
-
-I can then turn off the default HTML Report and plug the custom one in instead:
-
- Configurator.BatchProcessors.HtmlReport.Disable();
- Configurator.BatchProcessors.Add(new HtmlReporter(new CustomHtmlReportConfiguration()));
-
-## Test Runner ##
-The Test Runner is quite straightforward. We just have to instantiate all of the specification classes and call the Run method. You could new up each class, use reflection to find all the classes that derive from ContextSpecification (as Iāve done here) or use an IoC container to store and retrieve them.
-
- public class TestRunner
- {
- public void Run()
- {
- RunTestsSequentially();
- RunBatchProcessors();
- }
-
- private void RunTestsSequentially()
- {
- //new WhenAccountHasInsufficientFunds().Run();
- //new WhenCardHasBeenDisabled().BDDfy();
- //new WhenAccountHasSufficientFunds().BDDfy();
-
- GetSpecs().Each(spec => SafeRunSpec(spec));
- }
-
- private void SafeRunSpec(ContextSpecification spec)
- {
- try
- {
- spec.Run();
- }
- catch (Exception)
- {
- }
- }
-
- private void RunBatchProcessors()
- {
- foreach (var batchProcessor in Configurator.BatchProcessors.GetProcessors())
- {
- batchProcessor.Process(StoryCache.Stories);
- }
- }
-
- private List GetSpecs()
- {
- return this.GetType()
- .Assembly
- .GetTypes()
- .Where(type => type.IsSubclassOf(typeof(ContextSpecification)))
- .Select(Activator.CreateInstance)
- .Cast()
- .ToList();
- }
- }
-
-
-If you were to just run the tests like this then you would see the Console Report display all the tests in the console window. However, none of the Batch Processors, such as the HTML Report, would run. BDDfy runs these in the AppDomain_Unload event and one down side of my running in a console app is that [this event is not raised in the default application domain](http://msdn.microsoft.com/en-us/library/system.appdomain.domainunload%28VS.90%29.aspx). No worries, BDDfy makes it easy to run ourselves so Iāve added the RunBatchProcessors method. If you check the bin directory of the console application you will see our customised HTML Report with the context specification grammar.
-
-## Wiring It All Up ##
-All that is left is to wire up a console application to run the tests. The first step is to configure BDDfy, which Iāve already shown. To run the tests I just need to instantiate the TestRunner and call the Run method.
-
- class Program
- {
- static void Main(string[] args)
- {
- ConfigureBDDfy();
- new TestRunner().Run();
-
- Console.ReadLine();
- }
-
- private static void ConfigureBDDfy()
- {
- Configurator.Scanners.DefaultMethodNameStepScanner.Disable();
- Configurator.Scanners.Add(() => new ContextSpecificationStepScanner());
-
- Configurator.Scanners.StoryMetaDataScanner = () => new StoryMetaDataScanner();
-
- Configurator.BatchProcessors.HtmlReport.Disable();
- Configurator.BatchProcessors.Add(new HtmlReporter(new CustomHtmlReportConfiguration()));
- }
- }
-
-If you go to the bin directory of the test project you should see the report file with the custom name, "ContextSpecifications.html," and all of the custom content inside it.
-
-
-
-
-# Running the tests in parallel #
-In the never ending quest for faster running tests, being able to run them in parallel can be a great way to speed things up. The first problem I have to solve is to batch up the list of tests into smaller lists of a fixed size that can be run in parallel. I found an excellent extension method for that by David Boike [here](http://www.make-awesome.com/2010/08/batch-or-partition-a-collection-with-linq/):
-
- public static class Extensions
- {
- public static IEnumerable> Batch(this IEnumerable collection, int batchSize)
- {
- List nextbatch = new List(batchSize);
- foreach (T item in collection)
- {
- nextbatch.Add(item);
- if (nextbatch.Count == batchSize)
- {
- yield return nextbatch;
- nextbatch = new List(batchSize);
- }
- }
- if (nextbatch.Count > 0)
- yield return nextbatch;
- }
- }
-
-Then I can add a method to the TestRunner that uses the Batch extension method to break the list of tests into batches that can be run using the [Parallel ForEach](http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.foreach.aspx) method. This is the parallel version of the standard, sequential foreach loop.
-
- private void RunTestsInParallel(int batchSize)
- {
- List theSpecs = GetSpecs();
- var batch = theSpecs.Batch(batchSize);
-
- Parallel.ForEach(batch, specs => specs.Each(spec => SafeRunSpec(spec)));
- }
-
-
-This can be plugged into the Run method by adding an optional batch size parameter, which allows the existing code to work as it is and for tests to run in parallel by passing a batchSize value of more than zero into the Run method.
-
- public class TestRunner
- {
- public void Run(int batchSize = 0)
- {
- if (batchSize == 0)
- {
- RunTestsSequentially();
- }
- else
- {
- RunTestsInParallel(batchSize);
- }
- RunBatchProcessors();
- }
- ...
- }
-
-## Batch Console Reporter ##
-There is one problem with this code though. The parallel nature of the loop means that multiple iterations may be executing at the same time and, as might be expected, the normal console report becomes quite jumbled.
-
-
-
-The solution is to run the console report after all of the tests have completed. This can be achieved by creating a new Console Reporter as a Batch Processor rather than a Processor. The Processor runs as each test is being executed and allows you to build up the report, whereas a Batch Processor has the advantage of running after all of the tests have finished (see the [Architecture Overview](/BDDfy/Customizing/ArchitectureOverview.html) post for more detail).
-
- public class MyConsoleReporter : IBatchProcessor
- {
- public void Process(IEnumerable stories)
- {
- var reporter = new ConsoleReporter();
- stories
- .ToList()
- .ForEach(story => reporter.Process(story));
- }
- }
-
-Then I just needed to add it to the Batch Processor pipeline and disable the built-in console report. For convenience I have just added it to the RunTestsInParallel method:
-
- private void RunTestsInParallel(int batchSize)
- {
- Configurator.Processors.ConsoleReport.Disable();
- Configurator.BatchProcessors.Add(new BatchConsoleReporter());
-
- List theSpecs = GetSpecs();
- var batch = theSpecs.Batch(batchSize);
-
- Parallel.ForEach(batch, specs => specs.Each(spec => SafeRunSpec(spec)));
- }
-
-
-
-
-So, there it is. A bit of a contrived example, but hopefully it has highlighted some of the extensibility points that BDDfy offers and provided some food for thought for some customizations that you might like to try yourself.
-
-The code is available on github:
-[https://github.com/mwhelan/BDDfySamples](https://github.com/mwhelan/BDDfySamples)
diff --git a/docs/Customizing/ExampleUnitTesting.md b/docs/Customizing/ExampleUnitTesting.md
deleted file mode 100644
index b5979c75..00000000
--- a/docs/Customizing/ExampleUnitTesting.md
+++ /dev/null
@@ -1,224 +0,0 @@
-# Example - Using BDDfy for unit testing
-# Introduction #
-Iāve been using BDDfy with NUnit for writing acceptance tests for quite awhile now. But for unit testing I have continued to use mspec with [machine fakes](https://github.com/machine/machine.fakes) and Moq for auto-mocking. The more I used BDDfy, the more I liked it, and the less I liked the context switch into another framework. I found myself wanting to write unit tests in the Given When Then format and didn't like having to maintain two sets of helper code for NUnit and mspec. I loved the reporting in BDDfy and started to think it would be pretty cool to have similar reporting for my unit tests. Basically, I wanted a consistent experience across all my automated testing.
-
-MSpec uses the [testcase class per fixture](http://xunitpatterns.com/Testcase%20Class%20per%20Fixture.html) style of testing, which is how I use BDDfy for acceptance testing, so it makes sense to continue with that style for the BDDfy unit tests. When I am doing acceptance tests I have a base ScenarioFor< T> class, where the T represents the System Under Test (SUT). Because these are full system tests, I resolve this SUT using the same inversion of control container that my application uses, which works nicely. The IoC container acts as a [SUT factory](http://blog.ploeh.dk/2009/02/13/SUTFactory/). With unit tests, I also want to have a SUT factory, but instead I want it to be an auto-mocking container.
-
-When we started writing unit tests for the [Seleno](http://teststack.github.io/pages/Seleno.html) project, I thought it would be a good opportunity to try some of these ideas out.
-
-# Specification Base Fixture #
-The Specification base fixture class wires up BDDFy. It provides methods that BDDfy knows about in its default configuration for setting up and tearing down the fixture (each test class will implement its own specific Given When Then methods that BDDfy will also find). The Run method has the NUnit Test attribute and so will be called by the testing framework and it just calls BDDFy to run the test. I prefer to use NUnit myself, but you could just as easily substitute XUnit or MsTest attributes if you prefer. One thing I really like about this approach is that I only have to put the TestFixture and Test attributes in this one class and then all of the test classes I create inherit them and don't need any attributes. All the test runners still picks the classes up as tests and ReSharper even puts its little run test icons in each test class as normal. This class is also the one place that BDDfy gets called.
-
- [TestFixture]
- public abstract class Specification : ISpecification
- {
- [Test]
- public virtual void Run()
- {
- string title = BuildTitle();
- this.BDDfy(title, Category);
- }
-
- protected virtual string BuildTitle()
- {
- return Title ?? GetType().Name.Humanize(LetterCasing.Title);
- }
-
- // BDDfy methods
- public virtual void EstablishContext() { }
- public virtual void Setup() { }
- public virtual void TearDown() { }
-
- public virtual Type Story { get { return GetType(); } }
- public virtual string Title { get; set; }
- public string Category { get; set; }
- }
-
-#Auto-Mocking #
-The SpecificationFor class inherits from the Specification class and adds an auto-mocking container for creating the SUT. An auto-mocking container decouples a unit test from the mechanics of creating the SUT and automatically supplies dynamic mocks in place of all of the SUT's dependencies. They are commonly implemented by combining an IoC container with a mocking framework, which is what I will be doing here. I prefer [NSubstitute](http://nsubstitute.github.io/) for mocking these days, so my friend [Rob Moore's](http://robdmoore.id.au/) [AutoSubstitute](http://nuget.org/packages/AutofacContrib.NSubstitute) auto-mocking container is ideal.
-
-The AutoSubstitute field provides access to the container for full access to its functionality. SubstituteFor is provided as a convenience method to gain access to NSubstitute substitutes.
-
- public abstract class SpecificationFor : Specification
- {
- public T SUT { get; set; }
- protected AutoSubstitute AutoSubstitute;
-
- protected SpecificationFor()
- {
- AutoSubstitute = CreateContainer();
- InitialiseSystemUnderTest();
- }
-
- public virtual void InitialiseSystemUnderTest()
- {
- SUT = AutoSubstitute.Resolve();
- }
-
- public TSubstitute SubstituteFor() where TSubstitute : class
- {
- return AutoSubstitute.ResolveAndSubstituteFor();
- }
-
- public override Type Story
- {
- get { return typeof(T); }
- }
-
- private static AutoSubstitute CreateContainer()
- {
- Action autofacCustomisation = c => c
- .RegisterType()
- .FindConstructorsWith(t => t.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
- .PropertiesAutowired();
- return new AutoSubstitute(autofacCustomisation);
- }
- }
-
-Notice that the InitialiseSystemUnderTest is virtual, so if you need to create the SUT yourself rather than having AutoSubstitute do it then you can just override it in your test class. It runs before any of the test methods so they can all safely interact with the SUT confident that it has been created.
-
-# What's in a Story? #
-When moving from scenarios to unit tests I had to think what I wanted to do with the Story that is part of BDD. BDDfy actually doesn't require stories, so one option was to do nothing. However, when you don't have a story the report shows the namespace instead, and I don't find that particularly helpful or attractive. A Story's purpose in BDD is to group related Scenarios and to provide metadata about that grouping, so I think the same logic can be applied to unit tests.
-
-By creating a base specification class that related tests inherit from, they will all be grouped together on the report, and the name of that class will be used in the heading, much like a Story grouping would look like on a BDD report. This class is often a convenient place to create variables that are common to all of the test cases. So, for example, if you create a base class called PageNavigatorSpecification, the report grouping will read "Specifications For: Page Navigator." That is achieved by adding the following custom story metadata scanner.
-
- public class SpecStoryMetaDataScanner : IStoryMetaDataScanner
- {
- public virtual StoryMetaData Scan(object testObject, Type explicityStoryType = null)
- {
- var specification = testObject as ISpecification;
- if (specification == null)
- return null;
-
- string specificationTitle = CreateSpecificationTitle(specification);
- var story = new StoryAttribute() {Title = specificationTitle};
- return new StoryMetaData(specification.Story, story);
- }
-
- private string CreateSpecificationTitle(ISpecification specification)
- {
- string suffix = "Specification";
- string title = specification.Story.Name;
- if (title.EndsWith(suffix))
- title = title.Remove(title.Length - suffix.Length, suffix.Length);
- return title;
- }
- }
-
-And here is what the specifications look like in the BDDfy report:
-
-
-
-# Unit Testing #
-Here is an example of some tests that we have written for Seleno using this approach. Firstly, an example of a Specification class, the grouping class analagous to the BDDFy story that all the PageReader specification classes will inherit from. There is normally no need to override the Story as the SpecificationFor class will automatically convert the generic T into an English name. In this case though it will convert PageReader< TestViewModel> into PageReader`, so it is a convenient hack to override the property with PageReaderSpecification which will more attractively produce "Page Reader" on the report.
-
- abstract class PageReaderSpecification : SpecificationFor>
- {
- public override Type Story
- {
- get { return typeof (PageReaderSpecification); }
- }
- }
-
-Each specification for the PageReader component inherits from the PageReaderSpecification. There are often no Given steps as the auto-mocking container has taken care of instantiating the SUT for you. It has also created a Substitute for the IExecutor dependency of the PageReader class and in the verification phase of the test you can just call SubstituteFor< IExecutor> to call NSubstitute verification methods on the substitute.
-
- class When_checking_an_element_exists_and_is_visible_with_property : PageReaderSpecification
- {
- public When_checking_an_element_exists_and_is_visible_with_property()
- {
- SUT.ExistsAndIsVisible(x => x.Item);
- }
-
- public void Then_it_should_execute_the_relevant_script_with_jquery_id_selector()
- {
- SubstituteFor()
- .Received()
- .ScriptAndReturn("$(\"#Item\").is(':visible')");
- }
- }
-
-This test shows that you can also setup Substitute behaviour in the setup phase of the test.
-
- class When_getting_a_web_element_strongly_typed_text : PageReaderSpecification
- {
- private DateTime _result;
- private readonly DateTime _the03rdOfJanuary2012At21h21 = new DateTime(2012, 01, 03, 21, 21, 00);
-
- [Given("Given a web element contains the text 03/01/2012 21:21")]
- public void Given_a_web_element_contains_the_text_03_01_2012_21_21()
- {
- SubstituteFor()
- .Element(Arg.Any())
- .Returns(SubstituteFor());
-
- SubstituteFor().Text.Returns("03/01/2012 21:21");
- }
-
- public void When_getting_the_web_element_matching_a_view_model_property()
- {
- _result = SUT.TextAsType(viewModel => viewModel.Modified);
- }
-
- public void Then_it_should_return_the_corresponding_typed_value_of_the_web_element_text()
- {
- _result.Should().Be(_the03rdOfJanuary2012At21h21);
- }
- }
-
-# Another approach #
-It's worth looking at another example of sharing a base context class. As I said above, it is not just for making the report work, it can be quite helpful to share context there. [Matt Honeycutt](http://trycatchfail.com/blog/) has an interesting style for reusing context classes in his very cool [SpecsFor BDD framework](http://specsfor.com/) that this approach also supports:
-
- public class given
- {
- public abstract class the_command_is_valid : SpecificationFor
- {
- protected void Given_the_command_is_valid()
- {
- SubFor>().Validate(Arg.Any()).Returns(new ExecutionResult(null));
- SubFor().ValidatorForCommand(Arg.Any()).Returns(SubFor>());
- }
- }
- }
-
- public class processing_a__valid_command : given.the_command_is_valid
- {
- private TestCommand _command = new TestCommand();
- private ExecutionResult _result;
-
- public void when_processing_a_valid_command()
- {
- _result = SUT.Execute(_command);
- }
-
- public void Then_the_processor_should_find_the_validator_for_the_command()
- {
- SubFor().Received().ValidatorForCommand(_command);
- }
-
- public void AndThen_validate_the_command()
- {
- SubFor>().Received().Validate(_command);
- }
-
- public void AndThen_the_processor_should_find_the_handler_for_the_command()
- {
- SubFor().Received().HandlerForCommand(_command);
- }
-
- public void AndThen_the_command_is_processed_successfully()
- {
- _result.IsSuccessful.Should().BeTrue();
- }
-
- public void AndThen_the_result_is_logged()
- {
- SubFor().Received().Info(Arg.Any());
- }
- }
-
-And this comes out very nicely on the report:
-
-
-
-
-You can find the code on [github](https://github.com/TestStack/TestStack.Seleno/tree/master/src/TestStack.Seleno.Tests/Specify).
diff --git a/docs/Customizing/index.md b/docs/Customizing/index.md
deleted file mode 100644
index 837a4599..00000000
--- a/docs/Customizing/index.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Customizing BDDfy
-BDDfy strives to be very extensible: Its core barely has any logic in it all its responsibilities are delegated to extensions, all of which are configurable. For example, if you don't like the reports it generates, you can write your custom reporter in a few lines of code.
-
-This section will look at the extensibility points and provide samples of customizing BDDfy.
diff --git a/docs/Usage/BDDExamples.md b/docs/Usage/BDDExamples.md
deleted file mode 100644
index 026b661e..00000000
--- a/docs/Usage/BDDExamples.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Examples
-
-
-## Actions as examples
-One of the benefits that BDDfy's approach has it its flexibility.
-
-``` csharp
-ExampleAction actionToPerform = null;
-int valueShouldBe = 0;
-var story = this.Given(_ => SomeSetup())
- .When(() => actionToPerform)
- .Then(_ => ShouldBe(valueShouldBe))
- .WithExamples(new ExampleTable("Action to perform", "Value should be")
- {
- { new ExampleAction("Do something", () => { _value = 42; }), 42 },
- { new ExampleAction("Do something else", () => { _value = 7; }), 7 }
- })
- .BDDfy();
-```
-
-When run you will get this:
-
-```
-Scenario: Can use actions in examples
- Given some setup
- When
- Then should be
-
-Examples:
-| Action to perform | Value should be |
-| Do something | 42 |
-| Do something else | 7 |
-```
-
-This can make your BDD test incredibly flexible and powerful.
diff --git a/docs/Usage/ExecutableAttributes.md b/docs/Usage/ExecutableAttributes.md
deleted file mode 100644
index 542aaeea..00000000
--- a/docs/Usage/ExecutableAttributes.md
+++ /dev/null
@@ -1,320 +0,0 @@
-# Executable Attributes
-
-Before I start I should mention that this post is going to look rather similar to the one about [Method Name Conventions](/BDDfy/MethodNameConventions.html) because these two methods are similar in nature. Also the samples provided in this post are by no means perfect BDD samples and are used only to demonstrate the API usage.
-
-As mentioned in the previous post BDDfy can scan your tests in one of two ways: using Reflective API and Fluent API. Reflective API uses some hints to scan your classes. You can provide these hints in two ways: using method name conventions and/or attributes. We have discussed [method name conventions](/BDDfy/MethodNameConventions.html) before and in this post we will only concentrate on `ExecutableAttribute`.
-
-In the reflective mode you could use Method Name Conventions to provide BDDfy with some hints about your test steps. That is all good; but in some cases you may need to explicitly specify your test steps and/or their title (or at least some of them):
-
-##You may need more control over the step title
-When using Method Name Conventions BDDfy uses your method name to generate the step title. This works in a lot cases; but in some cases you may need more control over your step title. For example your step title may need to have special characters; e.g. "Given the ATM doesn't have enough cash". For BDDfy to be able to derive this your method should be called "GivenTheAtmDoesn'tHaveEnoughCash" which of course is not a valid method name. Even if that was a valid method name the result would be "Given the atm doesn't have enough cash" where 'atm' is all lower case!
-
-##What if Method Name Conventions do not make sense?
-In vast majority of cases method name conventions make your methods and tests more readable and maintainable; but there may be cases when you want to use different method names because they may read better. As an example you may have a scenario that is written as:
-
-
-
-The last two methods, which are my 'Then' and 'And then' steps, do not comply with method name conventions and as such will not be picked up by BDDfy!
-
-##So what are ExecutableAttributes?
-In cases when method name conventions do not cut it for you, you may use `ExecutableAttribute` to nominate any method as a step. So let's just change the above example so it works:
-
-
-
-The only difference between this class and the previous implementation is the addition of the `ExecutableAttribute` on the last two methods. Now if you run the test you can see that these two methods have been picked up and run as part of scenario:
-
-
-
-It is also worth mentioning that the 'Given' and 'When' steps were picked up too using method name conventions! BDDfy runs the Method Name Convention and `ExecutableAttribute` scanners in a pipeline (using [Chain of Responsibility](http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern)) which means that for a method to be considered a step it has to either match the naming conventions or be decorated with `Executable` attribute.
-
-If a method matches both criteria then the one decorated with `ExecutableAttribute` wins. For example let's change the 'When' step to start with 'Then' (not that it makes sense; but for demonstration purposes only):
-
-
-using BDDfy.Core;
-using BDDfy.Scanners.StepScanners.ExecutableAttribute;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace BDDfy.ExecutableAttributes
-{
- [TestClass]
- public class ExecutableAttributesOverridingTheNamingConvention
- {
- [TestMethod]
- public void ShouldBeAbleToRunScenariosWithNonCompliantMethodNames()
- {
- this.BDDfy();
- }
-
- void GivenSomeMethodsDoNotComplyWithBDDfyMethodNameConventions()
- {
- }
-
- [Executable(ExecutionOrder.Transition, "When the methods are decorated with ExecutableAttributes")]
- void ThenExecutableAttributeIsApplied()
- {
- }
-
- [Executable(ExecutionOrder.Assertion, "BDDfy can pickup the steps")]
- void BDDfyCanPickupTheSteps()
- {
- }
-
- [Executable(ExecutionOrder.ConsecutiveAssertion, "which are decorated with the attribute")]
- void ThatAreDecoratedWithTheAttributes()
- {
- }
- }
-}
-
-
-Using Method Name Conventions this method would be picked up as a 'Then' step; but since it is decorated with `ExecutableAttribute` with `ExecutionOrder.Transition` (which translates to 'When') it is run as a 'When' step and gets the title specified in the attribute instead of the one driven from the method name by convention.
-
-
-
-##But dude, ExecutableAttribute is too technical
-Fair enough. That is more of an implementation detail plus an extension point that you should not normally care about. For that reason BDDfy comes with a set of predefined subclasses of `ExecutableAttribute` which are easier to use: `Given`, `AndGiven`, `When`, `AndWhen`, `Then` and `AndThen`. These attributes have default constructors that allow you to set a method as a step without having to provide a title in which case the title will be driven by the method name. They also have a constructor that allows you the specify the title which will override the default convention. Let's see that in action. Changing the last example to use these attributes:
-
-
-
-The only change here was to replace the `ExecutableAttribute` usage with `Then` and `AndThen` attributes. And here is the report:
-
-
-
-To spice things up a bit I am also overriding the scenario name. This is only to show that you can always override scenario title regardless of your preferred BDDfy API/mode.
-
-##Can I exclude a method from scan?
-Just like there are cases when your step method name does not comply with conventions there may be cases where you have a non-step method that just happens to comply with conventions. Consider the following example:
-
-
-
-Ok, admittedly that is a silly example; but it shows my point :o)
-
-There is a method called `WhenEzuelaIsNotSpelledLikeThisDude` which matches BDDfy's method name conventions. By default this method would be picked up as a step and run by BDDfy which is not what you want because it is there to support other methods in your scenario and is not a step. In cases like this, if you do not want to rename your method, you can use `IgnoreStepAttribute` like below:
-
-
-
-I just had to decorate the method with the attribute and now when I run the test that method is no longer picked up and run as a step which is my desired behavior.
-
-
-
-This is not necessarily related to the `Executable` attribute as such and is part of the Reflective Scanner's logic which applies to both method name conventions and executable attributes.
-
-##How to create your own dialect
-If you want to use another syntax for your BDD behaviors because you do not like Given, When, Then or because you are writing low-level tests that do not quite fit into the GWT model you can create your own syntax easily. Near the end of this series I am writing a few posts dedicated to BDDfy extension points and how you can override and/or extend the framework easily. So I will just provide a small hint about this here and leave the full story for later.
-
-In this running mode the only thing BDDfy cares about is the `Executable` attribute; so you can very easily subclass it as I have done with the abovementioned attributes and create a new dialect and it will just work. For your reference this is the implementation of a few of the out of the box attributes:
-
-**[GivenAttribute](https://github.com/TestStack/TestStack.BDDfy/blob/master/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/GivenAttribute.cs)**
-
-public class GivenAttribute : ExecutableAttribute
-{
- public GivenAttribute() : this(null) { }
- public GivenAttribute(string stepTitle) : base(Core.ExecutionOrder.SetupState, stepTitle) { }
-}
-
-public class WhenAttribute : ExecutableAttribute
-{
- public WhenAttribute() : this(null) { }
- public WhenAttribute(string stepTitle) : base(Core.ExecutionOrder.Transition, stepTitle) { }
-}
-
-
-It is very easy to implement your own attribute and create your own dialect with BDDfy. You can also very easily override the existing Method Name Conventions to create a new dialect for conventions; but that is a matter of another post :)
-
-
-
- [10]: http://hg.mehdi-khalili.com/BDDfy/src/83fd2f4566c4/BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/GivenAttribute.cs
- [11]: http://hg.mehdi-khalili.com/BDDfy/src/83fd2f4566c4/BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/AndGivenAttribute.cs
- [12]: http://hg.mehdi-khalili.com/BDDfy/src/83fd2f4566c4/BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/WhenAttribute.cs
diff --git a/docs/Usage/FluentAPI.md b/docs/Usage/FluentAPI.md
deleted file mode 100644
index fa14c9b4..00000000
--- a/docs/Usage/FluentAPI.md
+++ /dev/null
@@ -1,185 +0,0 @@
-# Fluent API
-
-BDDfy can scan your tests in one of two ways: using Reflective API and Fluent API. Reflective API uses some hints to scan your classes. These hints are provided through [Method Name Conventions](/BDDfy/method-name-conventions.html) and/or `[ExecutableAttribute][/BDDfy/executable-attributes.html]` which we have discussed before. For this post we will concentrate on Fluent API.
-
-I just thought I would share a bit of history with you first. I had just released BDDfy V0.5 and the API had kinda settled. So I thought I'd write an [introductory article on CodeProject](http://www.codeproject.com/Articles/205381/Introduction-to-bddify-A-Simple-to-Use-and-Extend) to promote the framework. On the top of article I said '*BDDfy is very extensible. In fact, BDDfy core barely has any logic in it. It delegates all its responsibilities to its extensions*'. Then I thought that just claiming a framework is extensible does not mean anything if I cannot provide a sample for it. That is why I wrote the Fluent API as I was writing that article to prove it to myself that BDDfy is highly extensible and also to provide an example of that. Well, I started it as an extensibility example; but then I liked and felt the need for it and baked into the framework. Today it is no longer a sample and in fact it is even more popular than Reflective mode!!
-
-##Fluent API
-Fluent API of BDDfy does not really require much explanation as it is quite fluent ;-) So instead of trying to explain to you how it works I will just provide an example.
-
-In the Method Name Conventions post I wrote a scenario called 'BDDfyRocks' which I repeat here for your convenience:
-
-
-
-This class has two test methods each representing one of the scenarios. The reports generated by these tests are exactly the same as those shown in the [Method Name Conventions](/BDDfy/method-name-conventions.html) post.
-
-There are a few important differences in implementation as follows:
-
- - In Reflective API the only thing you need to call is `this.BDDfy();` or one of its overloads that accepts the story type argument and/or the custom scenario title (and then BDDfy will find your steps using conventions or attributes). In the Fluent API you should explicitly specify all your steps before calling the `BDDfy` method.
- - When using Reflective API the scenario name is driven by the name of the class because each class represents a scenario. In Fluent API, however, a class usually represents a story (or collection of related scenarios in the absence of a story) and scenarios are represented by methods. That is why while porting the sample to use Fluent API I renamed my scenario method names to match the class name that represented the scenario in the source sample. This is to ensure that I will get the same title for my scenarios after using Fluent API.
- - In Reflective API BDDfy would pick up any combination of scenario steps by method name conventions and `ExecutableAttribute`; but in Fluent API mode you are in complete control. This means that regardless of what your method names are or whether they are decorated with `ExecutableAttribute` or not the steps you specify using the Fluent API will run by BDDfy. Likewise if there is a method that complies with method name conventions and/or is decorated by `ExecutableAttribute` (or one of its derivatives) but is not specified in your Fluent API call it is not going to be picked up by the framework. Reflective and Fluent modes run in isolation of each other and you choose the mode by the way you call the `BDDfy` method.
- - In Reflective mode the method name starting with 'AndGiven' and 'AndWhen' will result into steps starting with 'And': the framework knows that you have provided the extra 'Given' and 'When' words only to comply with its conventions and as such drops them from the reports. In the Fluent API your step titles are derived directly from your method name. So when porting the example from using Method Name Convention to Fluent API I renamed `AndGivenIHaveNotUsedBDDfyBefore` to `AndIHaveNotUsedBDDfyBefore` to avoid getting 'And given' in my report.
- - You notice that I removed two methods while porting the code to use Fluent API: `WhenIAmIntroducedToTheFramework` and `ThenILikeItAndStartUsingIt`. These two methods were repeated in each scenario; but I ported all scenarios and methods to the same class; so we can avoid duplication. Well, in all fairness the same could be achieved in the Reflective mode through inheritance where the shared logic lives in a base class that other scenarios subclass; but I think the reuse is kinda more natural in the Fluent mode.
- - If you use R#, in Reflective mode if you write your steps as private methods you are going to get R# warning for unused methods because R# does not have any idea about the reflection magic going behind the scenes. Using Fluent API because you explicitly call the methods you no longer get the R# warning because you are using the methods. In order to avoid the warning in Reflective mode you may define your methods as protected or public to avoid the warnings.
-
-###Adding Story
-Out of the box, there is only one way to [specify your Story](/BDDfy/story.html) and to associate it with scenarios and that is using `StoryAttribute`. This is the same for Reflective and Fluent modes.
-
-Let's add story to the above example:
-
-
-using BDDfy.Core;
-using NUnit.Framework;
-
-namespace BDDfy.FluentApi
-{
- [Story(
- AsA = "As a .net programmer",
- IWant = "I want to use BDDfy",
- SoThat = "So that BDD becomes easy and fun")]
- public class BDDfySeriouslyRocks
- {
- [Test]
- public void BDDfyRocks()
- {
- this.Given(_ => GivenIHaveNotUsedBDDfyBefore())
- .When(_ => WhenIAmIntroducedToTheFramework())
- .Then(_ => ThenILikeItAndStartUsingIt())
- .BDDfy();
- }
-
- // The rest is removed for brevity
- }
-}
-
-
-As mentioned in a previous post, to create a story you need to decorate a class with `StoryAttribute`. In the Fluent mode the story class is usually the same as the class that contains the scenarios because, unlike Reflective mode, a scenario does not necessarily map to a class and is usually implemented in a method.
-
-This of course has its pros and cons. The nice thing about this approach is that you can see an entire story in one file/class; at the same time that could be considered a disadvantage because some stories are rather big and have quite a few scenarios which will result into a big class. Again you do not have to put all the scenarios of a story in one class: that is just one option.
-
-Running the tests now will include the story title and narrative into console and html reports.
-
-##FAQ
-These are some of the FAQs I have received for Fluent API:
-
-###Should I have my methods in the right order?
-In the Reflective mode there is a situation where you have to put your methods in the right order and that is when you have more than one 'AndGiven' or 'AndWhen' or 'And' in which you case the 'and' parts are executed in the order they appear in the class. In the Fluent API that does not matter. The methods are executed in the order specified using the Fluent API. So it does not matter in what order they appear in the class.
-
-###How I can reuse some of the testing logic?
-As mentioned above with Fluent API it is very easy to reuse the test logic across all scenarios of the same story because usually they are all in the same class. If the logic is not in the same class, you can still use inheritance or composition to compose a scenario.
-
-###Can my step methods be static or should they be instance methods?
-BDDfy handles both cases. So feel free to use whatever makes sense.
-
-
- [6]: http://www.mehdi-khalili.com/get/blogpictures/BDDfy-in-action/fluent-api/console-report-without-story.JPG
diff --git a/docs/Usage/FluentApiInputParameters.md b/docs/Usage/FluentApiInputParameters.md
deleted file mode 100644
index 072e41b4..00000000
--- a/docs/Usage/FluentApiInputParameters.md
+++ /dev/null
@@ -1,187 +0,0 @@
-# Fluent API Input Params
-
-In [the last post](/fluent-api.html) we discussed BDDfy's Fluent API and had a look at a very simple usage where we ported the example done using [Method Name Convention](/method-name-conventions.html) to use Fluent API. In this post we will discuss how you can provide input parameters to your step methods when using Fluent API.
-
-##Using input parameters
-In order to specify your step methods in Fluent API you provide BDDfy with some method call lambda expressions. In the examples we have seen so far we only called methods that did not have any input parameters; but BDDfy also supports input parameters. BDDfy inspects the provided expression and [extracts the input parameters](http://www.mehdi-khalili.com/extracting-input-arguments-from-expressions) you have passed and when it comes the execution time it calls those methods using the provided inputs. Alright let's see this in action. The example this time will be about modeling [Alcohol Laws in Australia](http://en.wikipedia.org/wiki/Alcohol_laws_of_Australia). As usual the examples you see here are created to show you the API usage.
-
-Let's see what the code would look like using Fluent API without overriding the titles and injecting input parameters:
-
-
-
-Hmmm, the method names are rather ugly and not very readable! How about the reports?
-
-
-
-The reports are a bit more readable due to spacing between words; but the dates are still cryptic. We can do better than that. Below I have added a new method to the same class in which I have overridden the default step title for the 'Given' and 'When' methods:
-
-
-[Test]
-public void AlcoholIsNotSoldToMinorsTake2()
-{
- this.Given(_ => GivenIWasBornOn01011998(), "Given I was born on 01-01-1998")
- .When(_ => WhenIAskToBuyAlcoholInALicencedPremiseOn01012012(), "When I ask to buy alcohol in a licenced permise on 01-01-2012")
- .Then(_ => ThenIDoNotGetTheAlocohol())
- .And(_ => AndIAmWalkedOut())
- .BDDfy("Alcohol is not sold to minors");
-}
-
-
-Please note that I also overrode the scenario title. This had to happen because I named my scenario method AlcoholIsNotSoldToMinorsTake2 which by default would result into scenario title 'Alcohol is not sold to minors take 2' which obviously is not what I want. So I overrode it to the title I'd be happy with.
-
-In this implementation the method names are still as unreadable as before; but the reports look a bit better as the dates are more readable:
-
-
-
-In this implementation the dates, that should be more like variables, are still part of my method names. This means that I cannot reuse the same method to write a test for happy path where for example someone over 18 years old can buy alcohol. So what can we do? Input parameters to the rescue. Let's change our methods to accept input parameters. Add the following code to the same class:
-
-
-
-Again I had to override the scenario title. This time I have implemented two methods that look exactly the same as my previous 'Given' and 'When' methods except that they accept the date as parameters. So in my scenario method I am providing the dates inline as input parameters. The code is now much more readable and the report looks like:
-
-
-
-As you can see in the report the input parameters are ToStringed and appended to step titles. This implementation solved the problems mentioned above. BDDfy can see that you are passing some input parameters to your lambda expressions; so it extracts them out and uses them to generate a step title. In this particular case, due to using DateTime, the result is less than perfect because of the time element; but other primitives will result in a much nicer output.
-
-... but that is not a good excuse and I want my dates to look good too, I hear you say. You can of course override the custom title behavior by passing a custom title in, like we did before; but we also want the custom title to be input-parameter aware. In other words we want the title to be formed based on the provided parameters:
-
-
-[Test]
-public void AlcoholIsNotSoldToMinorsTake4()
-{
- this.Given(_ => GivenIWasBornOn(new DateTime(1998, 1, 1)), "Given I was born on {0:dd-MMM-yyyy}")
- .When(_ => WhenIAskToBuyAlcoholInALicencedPremiseOn(new DateTime(2012, 1, 1)), "When I ask to buy alcohol in a licenced premise on {0:dd-MMM-yyyy}")
- .Then(_ => ThenIDoNotGetTheAlocohol())
- .And(_ => AndIAmWalkedOut())
- .BDDfy("Alcohol is not sold to minors");
-}
-
-
-This time I have overridden the default title by providing a custom one; but the custom title has a placeholder for my input parameter which also accepts [string formatter](http://msdn.microsoft.com/en-us/library/8kb3ddd4(v=VS.100).aspx). The report looks like (this time I use the html report for a change):
-
-
-
-The report this time is much more readable. I also used a date format that avoids confusion for American readers where 01-05-1998, for example, indicates 5th of January. The formatters are standard .Net formatters and this allows you to make your reports more readable when dealing with things like currency, date, time, decimal numbers and so on. It is worth highlighting that you do not necessarily have to provide a format string and can only use the placeholders.
-
-When you do not override the default title behavior BDDfy appends the input parameters at the end of the step title; but in some cases you want the parameter to appear in the middle of the title. For example assume I have a scenario where my 'Given' part should read as "Given I was born between 'May 1950' and 'June 1990'". If I wrote it as:
-
-
-this.Given(_ =>
- GivenIWasBornBetween(
- new DateTime(1950, 5, 1),
- new DateTime(1990, 6, 1))
-
-
-Then my title would be "Given I was born between 01/05/1950 12:00:00 AM, 01/06/1990 12:00:00 AM"!!! To get the result I wanted I would have to override my title as:
-
-
-this.Given(_ =>
- GivenIWasBornBetween(
- new DateTime(1950, 5, 1),
- new DateTime(1990, 6, 1),
- "Given I was born between '{0:MMMM yyyy}' and '{1:MMMM yyyy}'")
-
-
-which gives me "Given I was born between 'May 1950' and 'June 1990'" including the quotes.
-
-So we can easily format our title using placeholders and formatters; but what if I do not want my input parameters to be shown in the report?!! There are cases where you want to provide input parameters to a method but do not want it to be included in the title. This is usually the case when you are reusing the same method, that takes input parameters, for several scenarios.
-
-
-
-In this example, for the 'Given' step I do not care when "*I*" was born but still want to pass the date of birth to the step method. If I ran this scenario as is I would get:
-
-
-
-The 'Given' part does not look good at all as the date should not appear in the end. To remove the date from the end I will use another overload. The [overload's signature for the Given](https://github.com/TestStack/TestStack.BDDfy/blob/master/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentScanner.cs#L145) method looks like:
-
-
-[Test]
-public void AlcoholIsNotSoldToMinorsParametersNotShownInTheReportTake2()
-{
- this.Given(_ => GivenIAmAMinor(new DateTime(1998, 1, 1)), false)
- .When(_ => WhenIAskToBuyAlcoholInALicencedPremise())
- .Then(_ => ThenIDoNotGetTheAlocohol())
- .And(_ => AndIAmWalkedOut())
- .BDDfy("Alcohol is not sold to minors");
-}
-
-
-which results into:
-
-
diff --git a/docs/Usage/MethodNameConventions.md b/docs/Usage/MethodNameConventions.md
deleted file mode 100644
index 9ff1a2ab..00000000
--- a/docs/Usage/MethodNameConventions.md
+++ /dev/null
@@ -1,203 +0,0 @@
-# Method Name Conventions
-
-BDDfy can scan your tests in one of two ways: using Reflective API and Fluent API. Reflective API uses some hints to scan your classes and afterwards pretty much all the burden is on BDDfy's shoulders to find your steps, make sense of them and execute them in order. You can provide these hints in two ways: using method name conventions and/or attributes. For this post we will only concentrate on method name conventions.
-
-BDDfy uses a bit of magic to figure out what your scenario looks like and what it should execute. Despite the magic behind the scenes, using the BDDfy API is extremely simple - it boils down to 14 letters:
-
- this.BDDfy();
-
-That is all the API you need to know to be able to use BDDfy in Reflective Mode. Well, that and a bit of knowledge about the conventions described below.
-
-##A class per scenario
-In the reflective mode BDDfy associates each class with a scenario and you will basically end up with one class per scenario.
-
-Some developers like the Single Responsibility Principle forced nature of this approach and some do not. For those who think this is not very DRY (Don't Repeat Yourself) BDDfy allows you to take full control over this using the Fluent API. I personally use both approaches in every project because each has its pros and cons.
-
-A typical example of using method name convention looks like:
-
-
-
-The only thing related to BDDfy in this class is this.BDDfy();!!
-
-As mentioned in the [index page](/BDDfy/index.html), BDDfy does not care what testing framework or test runner you use and it provides the same result for all of them. Here is the result of the test run using R#:
-
-
-
-Using that one line of code BDDfy was able to find out what your scenario title and test steps are and how to run them! It also provides the above console report and an html report as below:
-
-
-
-##How does BDDfy do all that?
-When using the reflective mode, BDDfy scans your class (which is this you are calling BDDfy() on) and finds all the methods in it. It then adds all the methods which match its conventions to a list. After having gone through the class (and its base classes), it loops over the methods, executes them, and then generates a report.
-
-Here is the complete list of the out of the box conventions. The method name:
-
- * ending with "Context" is considered as a setup method (not reported).
- * "Setup" is considered as as setup method (not reported).
- * starting with "Given" is considered as a setup method (reported).
- * starting with "AndGiven" is considered as a setup method that runs after Context, Setup and Given steps (reported).
- * starting with "When" is considered as a transition method (reported).
- * starting with "AndWhen" is considered as a transition method that runs after When steps (reported).
- * starting with "Then" is considered as an asserting method (reported).
- * starting with "And" is considered as an asserting method (reported).
- * starting with "TearDown" is considered as a finally method which is run after all the other steps (not reported).
-
-Some of these special conventions will lead to the step not being reported. For example if your method name ends with the word 'Context' the step will be picked up by the framework and will be executed; but it will not be reported in console or html report. This was created on a request by a user; but I personally do not use this feature. If I need to setup my state I either do it in the 'Given' steps or in the class constructor if it is not directly related to the scenario state.
-
-It is worth mentioning that these conventions can be easily overridden if your needs require further customisation.
-
-BDDfy by default uses your scenario class name to generate a title for your scenario, however you can easily override this behaviour as we will see further down.
-
-##Another example
-Let's expand on the example above and create something a bit more complex. My specification this time reads as:
-
-
-Given I am new to BDD
- And I have not used BDDfy before
-When I am introduced to the framework
-Then I like it and I start using it
- And I learn BDD through BDDfy
-
-
-Not much difference to what I had before; but now I have two additional 'And' steps: one for 'Given' and one for 'Then'. Going by the conventions explained above you should implement this like below:
-
-
-
-Let's run this. This time I use [TD.Net](http://www.testdriven.net/) to show you the result from another test runner:
-
-
-
-So BDDfy was capable to find the 'AndGiven' method and turn it into an 'And' step that runs after the 'Given' step. The same goes for the 'And' method that is run after the 'Then' step.
-
-##How to use input arguments with method name conventions?
-If your test requires input arguments there is a good chance you should be using the fluent API; that said BDDfy provides support for input arguments for the method name convention scanner too.
-
-In order to run the same scenario using different input arguments you need to create a scenario class which is not a test class. The scenario class should accept the input arguments through constructor parameters and then you may assign those to instance fields and use them in your step methods. You then will have another class, which will usually be your story class, to instantiate your scenario class using different input arguments and call BDDfy on the instance. It is hard to explain this and an example shows the usage better.
-
-BDDfy comes with two complete examples that showcase different most BDDfy features. You may install these samples through BDDfy.Samples.TicTacToe and BDDfy.Samples.ATM. This particular feature is used in the [TestStack.BDDfy.Samples](http://nuget.org/packages/TestStack.BDDfy.Samples) sample for testing the winner games. You may see the winner game scenario class [here](https://github.com/TestStack/TestStack.BDDfy/blob/master/TestStack.BDDfy.Samples/TicTacToe/WinnerGame.cs). For brevity I only include the class constructor here:
-
-
-
-... and the code from the story that instantiates the class and runs it using different input arguments can be found [here](https://github.com/TestStack/TestStack.BDDfy/blob/master/TestStack.BDDfy.Samples/TicTacToe/TicTacToe.cs#L93). A bit of code copied from that codebase is shown below for your convenience:
-
-
-[Test]
-[TestCase("Vertical win in the right", new[] { X, O, X }, new[] { O, O, X }, new[] { O, X, X }, X)]
-[TestCase("Vertical win in the middle", new[] { N, X, O }, new[] { O, X, O }, new[] { O, X, X }, X)]
-[TestCase("Diagonal win", new[] { X, O, O }, new[] { X, O, X }, new[] { O, X, N }, O)]
-[TestCase("Horizontal win in the bottom", new[] { X, X, N }, new[] { X, O, X }, new[] { O, O, O }, O)]
-[TestCase("Horizontal win in the middle", new[] { X, O, O }, new[] { X, X, X }, new[] { O, O, X }, X)]
-[TestCase("Vertical win in the left", new[] { X, O, O }, new[] { X, O, X }, new[] { X, X, O }, X)]
-[TestCase("Horizontal win", new[] { X, X, X }, new[] { X, O, O }, new[] { O, O, X }, X)]
-public void WinnerGame(string title, string[] firstRow, string[] secondRow, string[] thirdRow, string expectedWinner)
-{
- new WinnerGame(firstRow, secondRow, thirdRow, expectedWinner).BDDfy(title);
-}
-
-
-This runs the WinnerGame test class as several scenarios with different inputs. The html report from the sample is shown below:
-
-
-
-The report has a story which I have not covered yet.
-
-So far we have been calling BDDfy() with no arguments so you may wonder what the title argument does. As you may guess from its name that argument overrides the scenario title. If we had not passed that argument in we would end up with 7 scenarios all titled 'Winner game' which is not what we want. So we pass in the title we want for the scenario based on the input arguments.
-
-##FAQ
-These are some of the FAQs I have received for Method Name Conventions:
-
-#####Should I have my methods in the right order?
-Ordinarily, no. BDDfy picks the methods based on the naming convention and regardless of where in the class they appear BDDfy runs and reports them in the right order. However, if you have multiple 'AndGiven', 'AndWhen', or 'And' steps you need to put these methods in the order that you want BDDfy to pick them up.
-
-If for some reason you are using both a Setup method and an xxxContext method to perform some setup then these will run in the order in which they are defined in your class. It is probably a better idea to refactor these into a single method if possible.
-
-#####How I can reuse some of the testing logic?
-You may achieve that through scenario inheritance or composition as you would in your business logic code.
-
-When inheriting from a base class that has a few steps BDDfy picks the steps from your base classes as if they were in your scenario class. This is useful when you have several scenarios that share a few steps. This way you put the shared steps in the base class and subclass that in your scenario classes.
-
-Using composition you may put the actual logic in a separate class and use them from your scenario classes. If you are using composition then you may want to consider the fluent API because it does just what you want. I will discuss them in another post in near future.
-
-#####Why does not BDDfy pick up my base class methods?
-Because you should define them either as public or protected. BDDfy ignores the base class methods with private access modifier.
-
-#####Can my step methods be static or should they be instance methods?
-BDDfy handles both cases. So feel free to use whatever makes sense.
-
-#####Where can I setup my mocks or other bits not directly related to the scenario?
-When unit testing you usually end up mocking a few interfaces and setting up a few things that are not necessarily related to the scenario under test, but are necessary for you to be able to test the scenario. I usually put this logic into the class constructor. If what you are setting up is directly related to the scenario then you should put the logic in your 'Given' step(s).
diff --git a/docs/Usage/Reports.md b/docs/Usage/Reports.md
deleted file mode 100644
index 0ea59b5b..00000000
--- a/docs/Usage/Reports.md
+++ /dev/null
@@ -1,121 +0,0 @@
-# Reports
-
-BDDfy provides a rich array of reports to choose from and is also very easy to extend if you want to add your own reports. The two main reports are the Console Report and the HTML Report and both of these are on by default, though you can turn them off if you want to. In addition there is a Markdown Report, and recently a Diagnostics Report using JSON has been added. Both of these are off by default.
-
-##The Reports
-I am going to start with an overview of the different reports available in BDDfy, using the ATM sample, available in the [BDDfy source code](https://github.com/TestStack/TestStack.BDDfy/tree/master/Samples/TestStack.BDDfy.Samples/Atm), or on [NuGet][3].
-
-###Console Report
-The Console Report is what provides feedback in Visual Studio when you run your tests. If you run the tests with TestDriven.Net then you will see the output from all the tests in the output window.
-
-
-
-At the end of the report it will also provide a summary of how many tests passed, failed, or were skipped and how long the tests took to run.
-
-
-
-If you run the tests in ReSharper then you see the output of each test individually when you select it in the Unit Test Sessions window.
-
-
-
-When the test passes, you just see the Scenario listed out, and its story if it has one. If the test fails, or is not implemented yet, then you will also see details alongside each step of which steps were executed and what their status was and an exception trace detailing the error information.
-
-
-
-###HTML Report
-If you are practicing BDD, then you will probably be interested in living documentation. BDDfy can help with this with its HTML report, which dev teams can share with their customers to see the progress in a very user friendly and accessible way. Every time you run tests with BDDfy it creates an HTML report in the bin directory of the test project. The report has a summary at the top, listing out how many Stories/Scenarios have run, and the totals for each type of execution result. The report is interactive, and lets you expand and collapse individual stories and scenarios or all at once. The report is very customisable and you are able to change the header, description, and the location where the report is saved to. You can also add your own CSS and JavaScript files to really open up the customisation possibilities.
-
-
-
-###Markdown Report
-The Markdown Report can be turned on using the BDDfy Configurator (more on that below). The report is written in the [GitHub Flavoured Markdown][9] format. Markdown is a really useful format for documenting (I write this blog in markdown). A possible use for this would be as part of efforts to generate documentation, which might be particularly useful for open source developers to generate wiki documents from their code, for example.
-
-The Markdown Report is output to the bin directory of the test project and is named BDDfy.md. The picture below shows the BDDfy.md file in the MarkPad markdown editor. The left pane shows the raw text view and the pane on the right shows how it would be displayed on a web page.
-
-
-
-###Diagnostics Report
-The Diagnostics Report is the most recent addition to the BDDfy stable. It is also off by default and can be turned on using the BDDfy Configurator. In BDDfy we can measure how long every step took to execute and then aggregate that data to see how long each Scenario and Story took to execute. This is particularly useful information if you have long running tests, such as browser-based functional tests, and want to identify the parts of the test that are having the worst impact on performance. For example, is it particularly slow when interacting with the database, or is it perhaps the rendering of the web pages?
-
-The Diagnostics Report is created in the JSON format. This is useful if you want to load the data into another system, perhaps to persist test runs to compare performance over time. The Diagnostics Report is output to the bin directory of the test project and is named Diagnostics.json. Here is the output for the ATM tests.
-
- {
- "Stories":
- [
- {
- "Name":"Account holder withdraws cash",
- "Duration":8,
- "Scenarios":
- [
- {
- "Name":"Account has insufficient fund",
- "Duration":8,
- "Steps":
- [
- {
- "Name":"Given the Account Balance is $10",
- "Duration":1
- },
- {
- "Name":"And the Card is valid",
- "Duration":0
- },
- {
- "Name":"And the machine contains enough money",
- "Duration":0
- },
- {
- "Name":"When the Account Holder requests $20",
- "Duration":0
- },
- {
- "Name":"Then the ATM should not dispense any Money",
- "Duration":5
- },
- {
- "Name":"And the ATM should say there are Insufficient Funds",
- "Duration":0
- },
- {
- "Name":"And the Account Balance should be $20",
- "Duration":0
- },
- {
- "Name":"And the Card should be returned",
- "Duration":0
- }
- ]
- }
- ]
- }
- ]
- }
-
-
-##Configuring Reports
-
-The Configurator class is the main configuration point for BDDfy and should be called before all your tests run if you are wanting to change the default behaviour. For example, in NUnit you could call it from the SetUpFixture.
-
-BDDfy implements components as processors in a pipeline (using the [Chain of Responsibility pattern][11]) and reports are just another type of processor. Processors can be switched on and off using the Configurator class by calling the Enable or Disable methods. As previously mentioned, the Console Report and the HTML Report are both on by default. If you donāt want them to run then you can disable them like this:
-
- Configurator.Processors.ConsoleReport.Disable();
- Configurator.BatchProcessors.HtmlReport.Disable();
-
-Similarly, you can turn on the Markdown and Diagnostics reports:
-
- Configurator.BatchProcessors.MarkDownReport.Enable();
- Configurator.BatchProcessors.DiagnosticsReport.Enable();
-
-While this is great if you want to turn a processor off for all the tests, it isnāt much help if you want to just turn it on or off for some of the tests. Fortunately, there is also the the RunsOn method, which allows you to enable or disable processors using a predicate. This allows a lot of flexibility, and you could even choose to combine predicates so that, for example, half the tests ran with the Console Report and the other half ran with the Markdown Report.
-
- Configurator.Processors.ConsoleReport
- .RunsOn(scenario => scenario.GetType().Namespace.StartsWith("MyCompany.MyApp.Domain"));
- Configurator.Processors.MarkdownReport
- .RunsOn(scenario => !scenario.GetType().Namespace.StartsWith("MyCompany.MyApp.Domain"));
-
-###Getting reports without running the tests
-Having processors run in a pipeline leads to some interesting possibilities. One that I particularly like is that you can get all of the reports without actually running the tests. To do this you just need to turn off the TestRunner processor. The reports will still be generated, the only difference is that they will have a status of Not Executed!
-
- Configurator.Processors.TestRunner.Disable();
-
-This is really useful when you want to print out the reports as documentation but donāt want to have to wait for the tests to run.
diff --git a/docs/Usage/Story.md b/docs/Usage/Story.md
deleted file mode 100644
index 67004914..00000000
--- a/docs/Usage/Story.md
+++ /dev/null
@@ -1,166 +0,0 @@
-# Story
-In this post we will discuss how you can add story support to your BDD behaviors. As mentioned before and as we saw in the post about [Method Name Conventions](/BDDfy/MethodNameConventions.html) BDDfy does not force you to use stories. This could be quite useful for teams that do not work in an Agile environment. Forcing developers to come up with a story definition, while I believe is useful in many cases, could be less than optimal in some situations. For this reason you can `BDDfy` a scenario without associating it with a story; but that is more of an exception than a rule. So let's see how you can create stories and associate them with some scenarios.
-
-##How to create a story definition?
-In BDDfy for everything you want to do there are several options; there is one exception to this and that is defining stories. There is only one way to define a story and it is quite simple: to define a story all you need to do is to decorate a class, any class anywhere in your solution, with a `StoryAttribute`. Doing so creates a story that you can then associate with your scenarios. Here is an example of a story:
-
-
-namespace BDDfy.Story
-{
- [Story(
- AsA = "As a .net programmer",
- IWant = "I want to use BDDfy",
- SoThat = "So that BDD becomes easy and fun")]
- public class BDDfyRocks
- {
- }
-}
-
-
-All I have here is a class decorated with a `Story` attribute. By decorating this class you have setup your story metadata once and forever so you will not have to repeat this info for every scenario.
-
-##So how do I associate a story with a scenario?
-There are two ways to achieve this:
-
-###1. Let BDDfy find the association!
-BDDfy can associate a story with a scenario if the scenario is BDDfied in a method defined in the story class.
-
-Let's write a scenario:
-
-
-
-Please note that there is nothing related to BDDfy in this class. It is just a Plain Old C# Class which will eventually have some assertions in it. I can then BDDfy this scenario from my story class like:
-
-
-using BDDfy.Core;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace BDDfy.Story
-{
- [TestClass]
- [Story(
- AsA = "As a .net programmer",
- IWant = "I want to use BDDfy",
- SoThat = "So that BDD becomes easy and fun")]
- public class BDDfyRocks
- {
- [TestMethod]
- public void LetBDDfyFindTheStory()
- {
- new ShouldBeAbleToBDDfyMyTestsVeryEasily().BDDfy();
- }
- }
-}
-
-
-There are a few changes here:
-
- - I added MSTest and BDDfy namespaces on the top.
- - Decorated the story class with TestClass. This is an MSTest requirement.
- - Created a new method which is my scenario and instantiated and bddified my scenario from within the method.
-
-Let's run our only test with R#:
-
-
-
-If you compare this to the similar test we ran in the previous post you notice that this report shows a story on the top. The story details are picked up from the `StoryAttribute` on the class.
-
-And as you would expect the story details will appear in the html report too:
-
-
-
-In the html report scenarios will be categorized by their stories. You can also expand or collapse them by clicking on them or by clicking on the expand all and collapse all which will expand and collapse them all respectively.
-
-... but how does BDDfy know how to associate the story with the scenario? At runtime BDDfy walks up the stack trace until it finds your test method and then finds the declaring class and checks to see if it is decorated with a `StoryAttribute` and if yes it associates the two. This brings us to the next approach of associating the stories and scenarios which is the recommended approach; but before going further I would like to ask you to read [this article](http://www.mehdi-khalili.com/that-tricky-stacktrace) about the intricacy of stack trace. I will wait here until you read that.
-
-Read it?! At runtime JIT may decide to flatten a few method calls and for that reason BDDfy may or may not be able to find your story class. Basically if you are running or intending to ever run your tests in release mode then you must use the second approach.
-
-###2. Tell BDDfy which story to use!
-If you may run your tests in release mode, to avoid disappointment, you may want to explicitly associate a story with a scenario. This approach has some other advantages that I will explain shortly.
-
-In order to specify the story you should use an overload of `BDDfy` method which accepts a type argument for story. Here is the same example but using this overload:
-
-
-using BDDfy.Core;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace BDDfy.Story
-{
- [TestClass]
- [Story(
- AsA = "As a .net programmer",
- IWant = "I want to use BDDfy",
- SoThat = "So that BDD becomes easy and fun")]
- public class BDDfyRocks
- {
- [TestMethod]
- public void TellBDDfyWhatStoryToUse()
- {
- new ShouldBeAbleToBDDfyMyTestsVeryEasily().BDDfy<BDDfyRocks>();
- }
- }
-}
-
-
-
-The only difference here is that I am passing `BDDfyRocks` type as a type argument to the `BDDfy()` method. This runs the very same steps and provides the very same report as we saw above; except that this method is guaranteed to find the story regardless of your build configuration or CPU architecture.
-
-##How can I override the story title?
-By default BDDfy turns your story class name into the title for the story which appears in the reports. For example `BDDfyRocks` is turned into 'BDDfy rocks'. For what it is worth, the same logic is used to drive scenario and step titles.
-
-In the previous post we overrode a scenario title by passing the custom title into the `BDDfy()` method; but how can we override the story title? It is very simple: `StoryAttribute` has a `Title` property that you can set. If you leave that property alone BDDfy uses your story class name for the title; but if you set it, that value is used instead.
-
-As an example to override the title of the `BDDfyRocks` story we can set the title as follows:
-
-
-[Story(
- Title = "Setting the story title is very easy",
- AsA = "As a .net programmer",
- IWant = "I want to use BDDfy",
- SoThat = "So that BDD becomes easy and fun")]
-public class BDDfyRocks
-{
-}
-
-
-##How can I reuse the same story for scenarios in different projects?
-This is the only question I get asked every now and then about using stories. This usually happens when there are more than one test project in the solution and two tests/behaviors in two different projects happen to be related to the same story. This is where the second approach shines. When specifying the story in the `BDDfy()` the framework does not really care whether your scenario is being run within the story or is in the same class or in the same project. It is happy as long as it can see the story (which means as long as your code compiles).
-
-As an example the same scenario above could be written as (assuming that `AScenarioRunFromAnotherProject` lives in a different project):
-
-
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace BDDfy.Story
-{
- [TestClass]
- public class AScenarioRunFromAnotherProject
- {
- [TestMethod]
- public void TellBDDfyWhatStoryToUse()
- {
- new ShouldBeAbleToBDDfyMyTestsVeryEasily().BDDfy<BDDfyRocks>();
- }
- }
-}
-
-
-This works the exact same way as if the story is defined in the same project or on the same class.
diff --git a/docs/index.md b/docs/index.md
deleted file mode 100644
index 8bc37c81..00000000
--- a/docs/index.md
+++ /dev/null
@@ -1,757 +0,0 @@
-BDDfy (pronounced B D Defy) is the simplest BDD framework for .Net EVER! The name comes from the fact that it allows you to turn your tests into BDD behaviors simply.
-
-A few quick facts about BDDfy:
-
- - It can run with any testing framework. Actually you don't have to use a testing framework at all. You can just apply it on your POCO (test) classes!
- - It does not need a separate test runner. You can use your runner of choice. For example, you can write your BDDfy tests using NUnit and run them using NUnit console or GUI runner, Resharper or TD.Net and regardless of the runner, you will get the same result.
- - It can run standalone scenarios. In other words, although BDDfy supports stories, you do not necessarily have to have or make up a story to use it. This is useful for developers who work in non-Agile environments but would like to get some decent testing experience.
- - You can use underscored or pascal or camel cased method names for your steps.
- - You do not have to explain your scenarios or stories or steps in string, but you can if you need full control over what gets printed into console and HTML reports.
- - BDDfy is very extensible: it's core barely has any logic in it and it delegates all it's responsibilities to it's extensions all of which are configurable; e.g. if you don't like the reports it generates, you can write your custom reporter in a few lines of code.
-
-Using BDDfy, it is easier to switch to BDD. So if you are on a project with a couple of hundred tests already written and you think using BDD could make your tests more valuable, then BDDfy can help you with that. You are still going to need to make some changes; but hopefully they will be minimal.
-
-##Installation
-To use BDDfy:
-
- - Install NuGet if you have not already.
- - Go to 'Tools', 'Library Package Manager', and click 'Package Manager Console'.
- - In the console, type `Install-Package TestStack.BDDfy` and enter.
-
-This adds BDDfy assembly and its dependencies to your test project. If this is the first time you are using BDDfy you may want to check out the samples on NuGet. Just run `Install-Package TestStack.BDDfy.Samples` and it will load two fully working samples to your project.
-
-##Usage
-Let's see BDDfy in action. I am going to use [Dan North's ATM sample](http://dannorth.net/introducing-bdd/) for this. I will copy his sample here for your convenience:
-
-
-Story: Account Holder withdraws cash
-
-As an Account Holder
-I want to withdraw cash from an ATM
-So that I can get money when the bank is closed
-
-Scenario 1: Account has sufficient funds
-Given the account balance is $100
- And the card is valid
- And the machine contains enough money
-When the Account Holder requests $20
-Then the ATM should dispense $20
- And the account balance should be $80
- And the card should be returned
-
-Scenario 2: Account has insufficient funds
-Given the account balance is $10
- And the card is valid
- And the machine contains enough money
-When the Account Holder requests $20
-Then the ATM should not dispense any money
- And the ATM should say there are insufficient funds
- And the account balance should be $10
- And the card should be returned
-
-Scenario 3: Card has been disabled
-Given the card is disabled
-When the Account Holder requests $20
-Then the ATM should retain the card
- And the ATM should say the card has been retained
-
-
-In order to add BDDfy library to your test project:
-
- - In Visual Studio go to 'Tools', 'Library Package Manager', and click 'Package Manager Console'.
- - In the console, type `Install-Package TestStack.BDDfy` and enter.
-
-This installs BDDfy on your project. As part of installation, BDDfy copies a file called 'BDDfy.ReadMe.txt' in your project root folder. This file explains a bit about how BDDfy works as well as some of its conventions.
-
-I will start with the last scenario for this sample because it is simpler than other scenarios and we can focus more on BDDfy than on the scenario's implementation:
-
- using System;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
- using TestStack.BDDfy;
-
- namespace BDDfy.Samples.Atm
- {
- [TestClass]
- public class CardHasBeenDisabled
- {
- void GivenTheCardIsDisabled()
- {
- throw new NotImplementedException();
- }
-
- void WhenTheAccountHolderRequestsMoney()
- {
- }
-
- void ThenTheAtmShouldRetainTheCard()
- {
- }
-
- void AndTheAtmShouldSayTheCardHasBeenRetained()
- {
- }
-
- [TestMethod]
- public void Execute()
- {
- this.BDDfy();
- }
- }
- }
-
-This class represents our scenario and has one test method called Execute (it can be called anything). Inside this method, I have one line of code that calls BDDfy extension method on the instance. Let's run this test to see what happens. I am using ReSharper test runner to run the test:
-
-
-
-*Figure 1: CardHasBeenDisabled console report before the scenario is implemented*
-
-That is the console report BDDfy generates. Note that BDDfy tells you that the 'Given' step has not been implemented yet and the other steps were not executed.
-
-By default, BDDfy also generates an HTML report called 'BDDfy.Html' in your project's output folder:
-
-
-
-*Figure 2: CardHasBeenDisabled Html report before the scenario is implemented*
-
-HTML report shows the summary on the top and the details on the bottom. If you click on scenarios, it also shows you the steps of that scenario along with the step result (and in case of an exception, the stack trace). You have a lot of control over HTML report and can customize a lot of things. You can also inject your own custom css and Javascript to get full control over the styling too.
-
-
-Note: As indicated in HTML and console reports, 'Given' step was unsuccessful due to the exception. When there is an exception in 'Given' or 'When' steps BDDfy will not run the remaining steps. It is shown in the console report with '[Not Executed]' in front of steps and in the HTML report with 'Not Executed' icon. This is because if your 'Given' or 'When' steps fail, there is no reason to run other steps. This rule does not apply to asserting steps (i.e. 'Then' parts) which means that you could have three asserting steps with one of them failing and the other two passing. In this case, BDDfy runs all the steps and shows you which of your assertions failed.
-
-###Method naming conventions in reflective API
-BDDfy uses reflection to scan your classes for steps. In this mode, known as reflective mode, it has two ways of finding a step: using attributes and method name conventions. The following is the list of method name conventions:
-
- - Method name ending with `Context` is considered a setup method but doesn't get shown in the reports
- - Method name equaling `Setup` is a setup method but doesn't get shown in in the reports
- - Method name starting with `Given` is a setup step that gets shown in the reports
- - Method name starting with `AndGiven` and 'And_given_' are considered setup steps running after 'Given' steps which is reported.
- - Method name starting with `When` is considered a state transition step and is reported
- - Method name starting with `AndWhen` and `And_when_` are considered state transition steps running after 'When' steps and is reported
- - Method name starting with `Then` is an asserting step and is reported
- - Method name starting with `And` and `AndThen` and `And_then_` are considered an asserting steps running after 'Then' step and is reported
- - Method name starting with `TearDown` is considered as tear down method that is always run at the end but doesn't get shown in the reports.
-
-If you don't like Given When Then dialect you can write your own dialect and register it in a few lines of code.
-
-BDDfy uses method names to generate the step titles and uses the scenario class name to generate the scenario title. Ok, let's implement the steps:
-
- using Microsoft.VisualStudio.TestTools.UnitTesting;
- using TestStack.BDDfy;
-
- namespace BDDfy.Samples.Atm
- {
- [TestClass]
- public class CardHasBeenDisabled
- {
- private Card _card;
- Atm _subject;
-
- void GivenTheCardIsDisabled()
- {
- _card = new Card(false, 100);
- _subject = new Atm(100);
- }
-
- void WhenTheAccountHolderRequestsMoney()
- {
- _subject.RequestMoney(_card, 20);
- }
-
- void ThenTheAtmShouldRetainTheCard()
- {
- Assert.IsTrue(_subject.CardIsRetained);
- }
-
- void AndTheAtmShouldSayTheCardHasBeenRetained()
- {
- Assert.AreEqual(DisplayMessage.CardIsRetained, _subject.Message);
- }
-
- [TestMethod]
- public void Execute()
- {
- this.BDDfy();
- }
- }
- }
-
-For the purpose of this article, I am going to provide you with the fully implemented domain class here. This is, of course, not the way you would do it in a real test first methodology:
-
- namespace BDDfy.Samples.Atm
- {
- public class Atm
- {
- public int ExistingCash { get; private set; }
-
- public Atm(int existingCash)
- {
- ExistingCash = existingCash;
- }
-
- public void RequestMoney(Card card, int request)
- {
- if (!card.Enabled)
- {
- //CardIsRetained = true;
- Message = DisplayMessage.CardIsRetained;
- return;
- }
-
- if (card.AccountBalance < request)
- {
- Message = DisplayMessage.InsufficientFunds;
- return;
- }
-
- DispenseValue = request;
- card.AccountBalance -= request;
- }
-
- public int DispenseValue { get; set; }
-
- public bool CardIsRetained { get; private set; }
-
- public DisplayMessage Message { get; private set; }
- }
-
- public class Card
- {
- public int AccountBalance { get; set; }
- private readonly bool _enabled;
-
- public Card(bool enabled, int accountBalance)
- {
- AccountBalance = accountBalance;
- _enabled = enabled;
- }
-
- public bool Enabled
- {
- get { return _enabled; }
- }
- }
-
- public enum DisplayMessage
- {
- None = 0,
- CardIsRetained,
- InsufficientFunds
- }
- }
-
-Let's run the test again:
-
-
-
-*Figure 3. CardHasBeenDisabled scenario with buggy implementation - console report*
-
-
-
-*Figure 4. CardHasBeenDisabled with buggy implementation - HTML report*
-
-As mentioned above, BDDfy does not stop the execution when there is an exception on your asserting steps. In this case, you can see that 'Then the atm should retain the card' step has failed; but BDDfy has run the next step and it shows you that it has passed. Of course, the scenario will be red until all its steps pass.
-
-Both console and HTML reports show that my scenario has failed. It seems like I have a bug in my Atm class. So I fix the bug (i.e. uncomment the only commented line in the Atm class) and run the test again and this time I get green result:
-
-
-
-*Figure 5. CardHasBeenDisabled green console report*
-
-
-
-*Figure 6. CardHasBeenDisabled green HTML report*
-
-###ExecutableAttribute in reflective API
-Let's implement another scenario. This time, I will not bore you with the red and green phases:
-
- using Microsoft.VisualStudio.TestTools.UnitTesting;
- using TestStack.BDDfy;
- using TestStack.BDDfy.Scanners.StepScanners.ExecutableAttribute.GwtAttributes;
-
- namespace BDDfy.Samples.Atm
- {
- [TestClass]
- public class AccountHasInsufficientFund
- {
- private Card _card;
- private Atm _atm;
-
- // You can override step text using executable attributes
- [Given("Given the account balance is $10")]
- void GivenTheAccountBalanceIs10()
- {
- _card = new Card(true, 10);
- }
-
- void AndGivenTheCardIsValid()
- {
-
- }
-
- void AndGivenTheMachineContainsEnoughMoney()
- {
- _atm = new Atm(100);
- }
-
- [When("When the account holder requests $20")]
- void WhenTheAccountHolderRequests20()
- {
- _atm.RequestMoney(_card, 20);
- }
-
- void ThenTheAtmShouldNotDispenseAnyMoney()
- {
- Assert.AreEqual(0, _atm.DispenseValue);
- }
-
- void AndTheAtmShouldSayThereAreInsufficientFunds()
- {
- Assert.AreEqual(DisplayMessage.InsufficientFunds, _atm.Message);
- }
-
- void AndTheAccountBalanceShouldBe10()
- {
- Assert.AreEqual(10, _card.AccountBalance);
- }
-
- void AndTheCardShouldBeReturned()
- {
- Assert.IsFalse(_atm.CardIsRetained);
- }
-
- [TestMethod]
- public void Execute()
- {
- this.BDDfy();
- }
- }
- }
-
-This scenario is a bit more involved. Let's run the test and see the reports:
-
-
-
-*Figure 7. AccountHasInsufficientFund console report*
-
-
-
-*Figure 8. AccountHasInsufficientFund HTML report*
-
-When reflecting over your test class, BDDfy looks for a custom attribute called `ExecutableAttribute` on the methods and considers the method decorated with this attribute as a step. You can use attributes either when your method name does not comply with the conventions or when you want to provide a step text that reflection would not be able to create for you.
-
-To make it easier to use, `ExecutableAttribute` has a few subtypes that you can use. In this scenario, I used `GivenAttribute`, `WhenAttribute` and `AndThenAttribute` attributes because I wanted to show '$' in the step text that would not be possible using method name reflection. Other available attributes are `AndGivenAttribute`, `AndWhenAttribute` and `ThenAttribute`. If you think some other `ExecutableAttribute` could really help you, then you can very easily implement one.
-
-While we are talking about attributes, there is also an attribute called `IgnoreStepAttribute` that you can apply on a method you want BDDfy to ignore as a step. This is useful when you have a method whose name complies with naming conventions BDDfy uses; but is not really a step.
-
-As you may have noticed, we have not still implemented any story. BDDfy is capable of executing standalone scenarios and generating report from them which I think is quite useful for teams that do not do Agile/BDD but are interested in a better testing experience and reporting. In this example, we have a story though. So let's code it:
-
- using TestStack.BDDfy.Core;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- namespace BDDfy.Samples.Atm
- {
- [TestClass]
- [Story(
- AsA = "As an Account Holder",
- IWant = "I want to withdraw cash from an ATM",
- SoThat = "So that I can get money when the bank is closed")]
- public class AccountHolderWithdrawsCash
- {
- [TestMethod]
- public void AccountHasInsufficientFund()
- {
- new AccountHasInsufficientFund().BDDfy();
- }
-
- [TestMethod]
- public void CardHasBeenDisabled()
- {
- new CardHasBeenDisabled().BDDfy();
- }
- }
- }
-
-Any class decorated with a `StoryAttribute` represents a story. Using `StoryAttribute`, you can also specify the story narrative. To associate the story with its scenarios, you should implement a test method per scenario.
-
-That is it. Just before we run these tests, we should get rid of the Execute test methods in our scenario classes as we no longer need them. We only had them there because we implemented those as standalone scenarios. Now that our scenarios are part of a story, they should not run standalone. Let's run the tests again:
-
-
-
-*Figure 9. Scenarios moved to story - console report*
-
-We now have only one test class which includes two test methods; one per scenario. Also note that the story narrative is now appearing on the top of the console report for each scenario.
-
-
-
-*Figure 10. Scenarios moved to story - HTML report*
-
-In the HTML report, the story narrative appears only once above the story's scenarios.
-
-Note: In the summary section of the HTML report before we implemented the story, we had two namespaces. After adding the story, the namespace count turned into zero and now we instead have one story. BDDfy only counts namespaces for standalone scenarios.
-
-If you compare the above reports with the ones generated when we had `Execute` methods in the scenarios, you see that these reports group your scenarios by story instead of namespace which makes the reports more readable.
-
-###Fluent API
-Let's do our last scenario. For this one, I am going to use the Fluent API BDDfy provides:
-
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- namespace BDDfy.Samples.Atm
- {
- [TestClass]
- public class AccountHasSufficientFund
- {
- private Card _card;
- private Atm _atm;
-
- public void GivenTheAccountBalanceIs(int balance)
- {
- _card = new Card(true, balance);
- }
-
- public void AndTheCardIsValid()
- {
- }
-
- public void AndTheMachineContainsEnoughMoney()
- {
- _atm = new Atm(100);
- }
-
- public void WhenTheAccountHolderRequests(int moneyRequest)
- {
- _atm.RequestMoney(_card, moneyRequest);
- }
-
- public void ThenTheAtmShouldDispense(int dispensedMoney)
- {
- Assert.AreEqual(dispensedMoney, _atm.DispenseValue);
- }
-
- public void AndTheAccountBalanceShouldBe(int balance)
- {
- Assert.AreEqual(balance, _card.AccountBalance);
- }
-
- public void AndTheCardShouldBeReturned()
- {
- Assert.IsFalse(_atm.CardIsRetained);
- }
- }
- }
-
-This looks very much like the other scenarios with one difference: the naming conventions are not quite right and you think that BDDfy would fail to match some of these methods - specifically those starting with `And` instead of `AndGiven`. If you were to use reflecting scanners, those methods would have been picked up as asserting steps which meant they would run and report in incorrect order! You could very easily customise BDDfy's naming conventions or rename your methods or use `ExecutableAttribute` to make these methods scannable by reflecting scanners; but I wrote the class like this to show how you can use a fluent API to let BDDfy find your methods/steps:
-
- [TestMethod]
- public void AccountHasSufficientfund()
- {
- new AccountHasSufficientFund()
- .Given(s => s.GivenTheAccountBalanceIs(100), "Given the account balance is $100")
- .And(s => s.AndTheCardIsValid())
- .And(s => s.AndTheMachineContainsEnoughMoney())
- .When(s => s.WhenTheAccountHolderRequests(20),
- "When the account holder requests $20")
- .Then(s => s.ThenTheAtmShouldDispense(20), "Then the ATM should dispense $20")
- .And(s => s.AndTheAccountBalanceShouldBe(80),
- "And the account balance should be $80")
- .And(s => s.AndTheCardShouldBeReturned())
- .BDDfy();
- }
-
-You may write this method in your scenario class if you want to run it as a standalone scenario. I added it to my `AccountHolderWithdrawsCash` story to make it part of my story.
-
-By default, BDDfy uses two scanners namely `MethodNameStepScanner` and `ExecutableAttributeStepScanner` - which I collectively refer to as reflective scanners . The former scans your scenario class for steps using method name conventions and the latter looks for `ExecutableAttribute` on your methods. There is also a third scanner called `FluentStepScanner` which we used in the above example. You don't have to tell BDDfy which scanner to use: it picks the right scanner according to your code.
-
-Note: Reflective scanners run in a pipeline which means you can mix and match their usage in your scenario; however, when you use `FluentStepScanner`, BDDfy does not use other scanners which means method names and attributes are ignored for scanning methods. In other words, you are in full control of what steps you want run and in what order.
-
-For reporter modules, it does not make any difference what scanner you use; so the HTML and console reports are going to look the same regardless of the scanners.
-
-Using fluent API you can implement your stories/scenarios in an alternative and rather interesting way. Instead of having one class per scenario and a class for your story, you could write one class that represents all your scenarios as well as your story:
-
- using Microsoft.VisualStudio.TestTools.UnitTesting;
- using TestStack.BDDfy;
- using TestStack.BDDfy.Core;
- using TestStack.BDDfy.Scanners.StepScanners.Fluent;
-
- namespace BDDfy.Samples.Atm
- {
- [TestClass]
- [Story(
- Title = "Account holder withdraws cash",
- AsA = "As an Account Holder",
- IWant = "I want to withdraw cash from an ATM",
- SoThat = "So that I can get money when the bank is closed")]
- public class AccountHolderWithdrawsCashFluentScanner
- {
- private const string GivenTheAccountBalanceIsTitleTemplate =
- "Given the account balance is ${0}";
- private const string AndTheMachineContainsEnoughMoneyTitleTemplate =
- "And the machine contains enough money";
- private const string WhenTheAccountHolderRequestsTitleTemplate =
- "When the account holder requests ${0}";
- private const string AndTheCardShouldBeReturnedTitleTemplate =
- "And the card should be returned";
-
- private Card _card;
- private Atm _atm;
-
- public void GivenTheAccountBalanceIs(int balance)
- {
- _card = new Card(true, balance);
- }
-
- public void GivenTheCardIsDisabled()
- {
- _card = new Card(false, 100);
- _atm = new Atm(100);
- }
-
- public void AndTheCardIsValid()
- {
- }
-
- public void AndTheMachineContains(int atmBalance)
- {
- _atm = new Atm(atmBalance);
- }
-
- public void WhenTheAccountHolderRequests(int moneyRequest)
- {
- _atm.RequestMoney(_card, moneyRequest);
- }
-
- public void TheAtmShouldDispense(int dispensedMoney)
- {
- Assert.AreEqual(dispensedMoney, _atm.DispenseValue);
- }
-
- public void AndTheAccountBalanceShouldBe(int balance)
- {
- Assert.AreEqual(balance, _card.AccountBalance);
- }
-
- public void CardIsRetained(bool cardIsRetained)
- {
- Assert.AreEqual(cardIsRetained, _atm.CardIsRetained);
- }
-
- void AndTheAtmShouldSayThereAreInsufficientFunds()
- {
- Assert.AreEqual(DisplayMessage.InsufficientFunds, _atm.Message);
- }
-
- void AndTheAtmShouldSayTheCardHasBeenRetained()
- {
- Assert.AreEqual(DisplayMessage.CardIsRetained, _atm.Message);
- }
-
- [TestMethod]
- public void AccountHasInsufficientFund()
- {
- this.Given(s => s.GivenTheAccountBalanceIs(10),
- GivenTheAccountBalanceIsTitleTemplate)
- .And(s => s.AndTheCardIsValid())
- .And(s => s.AndTheMachineContains(100),
- AndTheMachineContainsEnoughMoneyTitleTemplate)
- .When(s => s.WhenTheAccountHolderRequests(20),
- WhenTheAccountHolderRequestsTitleTemplate)
- .Then(s => s.TheAtmShouldDispense(0), "Then the ATM should not dispense")
- .And(s => s.AndTheAtmShouldSayThereAreInsufficientFunds())
- .And(s => s.AndTheAccountBalanceShouldBe(10))
- .And(s => s.CardIsRetained(false),
- AndTheCardShouldBeReturnedTitleTemplate)
- .BDDfy();
- }
-
- [TestMethod]
- public void AccountHasSufficientFund()
- {
- this.Given(s => s.GivenTheAccountBalanceIs(100),
- GivenTheAccountBalanceIsTitleTemplate)
- .And(s => s.AndTheCardIsValid())
- .And(s => s.AndTheMachineContains(100),
- AndTheMachineContainsEnoughMoneyTitleTemplate)
- .When(s => s.WhenTheAccountHolderRequests(20),
- WhenTheAccountHolderRequestsTitleTemplate)
- .Then(s => s.TheAtmShouldDispense(20), "Then the ATM should dispense $20")
- .And(s => s.AndTheAccountBalanceShouldBe(80),
- "And the account balance should be $80")
- .And(s => s.CardIsRetained(false),
- AndTheCardShouldBeReturnedTitleTemplate)
- .BDDfy();
- }
-
- [TestMethod]
- public void CardHasBeenDisabled()
- {
- this.Given(s => s.GivenTheCardIsDisabled())
- .When(s => s.WhenTheAccountHolderRequests(20))
- .Then(s => s.CardIsRetained(true), "Then the ATM should retain the card")
- .And(s => s.AndTheAtmShouldSayTheCardHasBeenRetained())
- .BDDfy();
- }
- }
- }
-
-This way, you will not need a separate story class or one class per scenario - everything is mixed into one class. Running tests in this class generates the very same console and HTML reports.
-
-This style of writing stories and scenarios helps you be a bit DRYer; but one could argue it violates [SRP](http://en.wikipedia.org/wiki/Single_responsibility_principle). It is important to note that you could achieve [DRY](http://en.wikipedia.org/wiki/Don't_repeat_yourself)ness without using fluent API. In order to do that, you would need to use inheritance or composition to compose your scenario class from classes that would hold the common behaviors. For example, if you put your 'Given' and 'When' steps inside a base class and your 'Then' steps inside a subclass, BDDfy will scan all these steps into your scenario. That would not give you as much freedom as the fluent API though.
-
-###Titles
-By default, BDDfy uses the name of the story class for the story title as we saw in the first few samples. You can override this behavior by passing the title into the Story attribute as I have done in the above example. I named my class `AccountHolderWithdrawsCashFluentScanner` to differentiate it from the story class in the other implementation; but I do not want the story title to end with 'fluent scanner'. So I provided the story with a title I will be happy to see in the reports:
-
- [Story(
- Title = "Account holder withdraws cash",
- AsA = "As an Account Holder",
- IWant = "I want to withdraw cash from an ATM",
- SoThat = "So that I can get money when the bank is closed")]
- public class AccountHolderWithdrawsCashFluentScanner
-
-For scenario titles, BDDfy uses the class name; for example in the first scenario, BDDfy extracted the scenario text 'Card has been disabled' from the class name 'CardHasBeenDisabled'. In the above example, because all your scenarios are fetched from the same class, one would expect BDDfy to give them all the same title! That is not the case though. In this case, BDDfy detects that you are using fluent API and uses the test method's name to generate the scenario title. For example, the `CardHasBeenDisabled` method results into 'Card has been disabled'. That said, if you want to have full control over scenario title, you may pass the title to BDDfy method; e.g.
-
- [TestMethod]
- public void CardHasBeenDisabled()
- {
- this.Given(s => s.GivenTheCardIsDisabled())
- .When(s => s.WhenTheAccountHolderRequests(20))
- .Then(s => s.CardIsRetained(true), "Then the ATM should retain the card")
- .And(s => s.AndTheAtmShouldSayTheCardHasBeenRetained())
- .BDDfy("Card has been disabled and account holder requests $20");
- }
-
-BDDfy uses step method names for the method title and it is also capable of injecting the input arguments in the title. In the above example, `Given(s => s.GivenTheCardIsDisabled())` results into 'Given the card is disabled' and `When(s => s.WhenTheAccountHolderRequests(20))` results in 'When the account holder requests 20'; but sometimes that is not good enough (e.g., the account holder does not request 20 - s/he requests 20 dollars). In cases like this, if you are using the fluent API, you can pass in the desired title into the step indicator methods; e.g.
-
-`And(s => s.CardIsRetained(false), "And the card should be returned")`
-
-The string that you pass into these methods could also have placeholders for input arguments. This way, you can reuse a string template across several scenarios as I did above. I declared a const on the class level:
-
-`private const string GivenTheAccountBalanceIsTitleTemplate = "Given the account balance is ${0}";`
-
-...and then I used it in the step indicator methods like:
-
-`.Given(s => s.GivenTheAccountBalanceIs(10), GivenTheAccountBalanceIsTitleTemplate)`
-
-...which resulted in the step title: 'Given the account balance is $10'. It is worth mentioning that BDDfy uses the template in a string.Format() method to generate the title; so you may use as many placeholders and wherever in the title as you like as long as they match the method inputs.
-
-As mentioned before, when using reflecting scanners you may use `ExecutableAttribute` or a subtype of it to provide custom step texts. The string provided to these attributes also accepts placeholders that are filled by method input arguments.
-
-Reflective and fluent APIs offer similar functionalities (but some through different means). Below, you may find a quick comparison:
-
-
-
-
-
Functionality
-
Reflecting Scanners
-
Fluent Scanner
-
-
-
-
-
-
Story title from story class name
-
Yes
-
Yes
-
-
-
-
Story title from Title in StoryAttribute
-
Yes
-
Yes
-
-
-
-
Scenario title from scenario class name
-
Yes
-
No
-
-
-
-
Scenario title from test method name
-
No
-
Yes
-
-
-
-
Custom scenario title passed in BDDfy method
-
Yes
-
Yes
-
-
-
-
Implementing story and scenarios in one class
-
No
-
Yes
-
-
-
-
Finding step methods using naming convention
-
Yes
-
No
-
-
-
-
Finding step methods using attributes
-
Yes
-
No
-
-
-
-
Finding step methods using lambda expression
-
No
-
Yes
-
-
-
-
Running step methods with input arguments
-
Yes - using RunStepWithArgsAttribute
-
Yes - using lambda expression
-
-
-
-
Step title using step method name
-
Yes
-
Yes
-
-
-
-
Using input arguments in the step title
-
Yes
-
Yes
-
-
-
-
Custom step title
-
Yes - using attributes
-
Yes - passing into step indicator methods
-
-
-
-
Using the same method for several steps
-
Yes - using RunStepWithArgsAttribute
-
Yes
-
-
-
-
Ignoring a method as step
-
Yes - using IgnoreAttribute
-
N/A - Do not indicate the method
-
-
-
-
Dispose method
-
Yes - Implement a method starting with 'TearDown'
-
Yes - Use TearDownWith step indicator
-
-
-
-
Using inherited step methods
-
Yes
-
Yes
-
-
-
-
-
-You may think that these two APIs are significantly different and that a huge amount of effort has been put to implement both models; but the ONLY difference between these two models is in their step scanners which are not even part of the core. BDDfy is very extensible and the core barely has any logic in it. It instead delegates all its responsibilities to its extensions, one of which is step scanner implementing `IStepScanner`. The same applies to scenario scanner implemening `IScenarioScanner`, and story scanner implementing `IScanner`, report generators, test runner and exception handler etc. All these interfaces contain only one method which makes it rather straightforward to implement a new extension. Step scanners are a very small part of this framework, and if you think you could benefit from a different scanner you could very simply implement it.
-
-The sample we worked through in this article is one of the BDDfy samples. There are a few more samples that are implemented in different ways and use some other BDDfy features I did not explain here and I think are definitely worth looking. Samples are available on TestStack.BDDfy.Samples NuGet package. The samples are all implemented using NUnit; but as shown in this article you can use MSTest or any other testing framework.
diff --git a/images/bg_hr.png b/images/bg_hr.png
new file mode 100644
index 00000000..7973bd69
Binary files /dev/null and b/images/bg_hr.png differ
diff --git a/images/blacktocat.png b/images/blacktocat.png
new file mode 100644
index 00000000..6e264fe5
Binary files /dev/null and b/images/blacktocat.png differ
diff --git a/images/icon_download.png b/images/icon_download.png
new file mode 100644
index 00000000..a2a287f6
Binary files /dev/null and b/images/icon_download.png differ
diff --git a/images/sprite_download.png b/images/sprite_download.png
new file mode 100644
index 00000000..f2babd57
Binary files /dev/null and b/images/sprite_download.png differ
diff --git a/index.html b/index.html
new file mode 100644
index 00000000..71579258
--- /dev/null
+++ b/index.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+Redirecting to BDDfy portal
+
+
+
+
+
+
+
+
+
+
+
+
+This page has moved. You will be automatically redirected to its new location in 10 seconds.
+If you aren't forwarded to the new page, click here.
+
+
+
+
+
+
diff --git a/javascripts/main.js b/javascripts/main.js
new file mode 100644
index 00000000..d8135d37
--- /dev/null
+++ b/javascripts/main.js
@@ -0,0 +1 @@
+console.log('This would be the main JS file.');
diff --git a/license.txt b/license.txt
deleted file mode 100644
index ae5f0482..00000000
--- a/license.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2011-2013 TestStack.BDDfy Contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
\ No newline at end of file
diff --git a/logo.png b/logo.png
deleted file mode 100644
index ac87c2e5..00000000
Binary files a/logo.png and /dev/null differ
diff --git a/params.json b/params.json
new file mode 100644
index 00000000..9c5c5b71
--- /dev/null
+++ b/params.json
@@ -0,0 +1 @@
+{"tagline":"BDDfy is the simplest BDD framework EVER! ","note":"Don't delete this file! It's used internally to help with page regeneration.","google":"","body":"## What's with the name?\r\nThe framework is called BDDfy because it BDDfies (as in turns into BDD) your otherwise traditional unit tests. Oh and BTW it is pronounced B D Defy. With BDDfy it is very simple to turn your AAA tests into a BDD test/behavior. BDDfy can work with any and all testing frameworks. In fact, it works even if you are not using any testing framework.\r\n\r\nThe framework is explained on Mehdi Khalili's blog series in full details [here] (http://www.mehdi-khalili.com/bddify-in-action/introduction).\r\n\r\n## How to get going\r\n1. Install NuGet if you have not already.\r\n2. Go to 'Tools', 'Library Package Manager', and click 'Package Manager Console'.\r\n3. In the console, type 'Install-Package TestStack.BDDfy' and enter. \r\n\r\nThis adds the BDDfy assembly to your test project. \r\n\r\nIf this is the first time you are using BDDfy you may want to check out some of the samples on NuGet. Just search NuGet for BDDfy and you will see a list of BDDfy samples. You may install one or more samples to see how the framework works. Each sample installs required packages (including BDDfy and NUnit).\r\n\r\n## Highlights\r\n* BDDfy can run with any testing framework. It does not force you to use any particular framework. Actually BDDfy does not force you to use a testing framework at all. You can just apply it on POCO classes even in a console app if that is what you need!\r\n* BDDfy does not need a separate test runner. You can use your runner of choice. For example, if you like NUnit, then you may write your BDDfy tests using NUnit and run them using NUnit console or GUI runner, Resharper or TD.Net and regardless of the runner, you will get the same result. This means it integrates with the tools you know and love instead of adding yet another one on the top of them.\r\n* BDDfy can run standalone scenarios. Although BDDfy supports stories, you do not necessarily have to have or make up a story to use BDDfy. This is useful for developers who work in non-Agile environments but would like to get some decent testing experience.\r\n* You can use underscored or pascal or camel cased method names for your steps.\r\n* You do not have to explain your scenarios or stories or steps in string: BDDfy infers them based on conventions but you can override the conventions if you need full control over what gets printed into console and HTML reports. Conventions galore in BDDfy and pretty much everything has a convention; but it is also very easy to override these conventions.\r\n* BDDfy is very extensible. In fact, BDDfy core barely has any logic in it. It delegates all its responsibilities to its extensions.\r\n* BDDfy learning curve is rather flat. Not only that but it makes learning BDD effortless.\r\n\r\n##Quick start\r\nNow that you have installed BDDfy, write your first test (this test is borrowed from ATM sample that you can install using nuget package TestStack.BDDfy.Samples):\r\n\r\n\t[Story(\r\n AsA = \"As an Account Holder\",\r\n IWant = \"I want to withdraw cash from an ATM\",\r\n SoThat = \"So that I can get money when the bank is closed\")]\r\n\tpublic class AccountHasInsufficientFund\r\n\t{\r\n\t private Card _card;\r\n\t private Atm _atm;\r\n\t\r\n\t // You can override step text using executable attributes\r\n\t [Given(StepText = \"Given the account balance is $10\")]\r\n\t void GivenAccountHasEnoughBalance()\r\n\t {\r\n\t _card = new Card(true, 10);\r\n\t }\r\n\t\r\n\t void AndGivenTheCardIsValid()\r\n\t {\r\n\t }\r\n\t\r\n\t void AndGivenTheMachineContainsEnoughMoney()\r\n\t {\r\n\t _atm = new Atm(100);\r\n\t }\r\n\t\r\n\t void WhenTheAccountHolderRequests20()\r\n\t {\r\n\t _atm.RequestMoney(_card, 20);\r\n\t }\r\n\t\r\n\t void ThenTheAtmShouldNotDispenseAnyMoney()\r\n\t {\r\n\t Assert.AreEqual(0, _atm.DispenseValue);\r\n\t }\r\n\t\r\n\t void AndTheAtmShouldSayThereAreInsufficientFunds()\r\n\t {\r\n\t Assert.AreEqual(DisplayMessage.InsufficientFunds, _atm.Message);\r\n\t }\r\n\t\r\n\t void AndTheCardShouldBeReturned()\r\n\t {\r\n\t Assert.IsFalse(_atm.CardIsRetained);\r\n\t }\r\n\t\r\n\t [Test]\r\n\t public void Execute()\r\n\t {\r\n\t this.BDDfy();\r\n\t }\r\n\t}\r\n\r\n\r\nAnd this gives you a report like:\r\n\r\n\tStory: Account holder withdraws cash\r\n \tAs an Account Holder\r\n \tI want to withdraw cash from an ATM\r\n \tSo that I can get money when the bank is closed\r\n\r\n\tScenario: Account has insufficient fund\r\n \tGiven the account balance is $10\r\n \t\tAnd the card is valid\r\n \tWhen the account holder requests $20\r\n \tThen the atm should not dispense any money\r\n \t\tAnd the atm should say there are insufficient funds\r\n \t\tAnd the card should be returned\r\n\r\nThis is just the console report. Have a look at your output folder and you should see a nice html report too.\r\n\r\nIf you want more control you can also use BDDfy's Fluent API. Here is another example done using the Fluent API:\r\n\r\n\r\n\t[Test]\r\n\tpublic void CardHasBeenDisabled()\r\n\t{\r\n\t this.Given(s => s.GivenTheCardIsDisabled())\r\n\t .When(s => s.WhenTheAccountHolderRequests(20))\r\n\t .Then(s => s.CardIsRetained(true), \"Then the ATM should retain the card\")\r\n\t .And(s => s.AndTheAtmShouldSayTheCardHasBeenRetained())\r\n\t .BDDfy(htmlReportName: \"ATM\");\r\n\t}\r\n\r\nwhich gives you a report like:\r\n\r\n\tScenario: Card has been disabled\r\n \tGiven the card is disabled\r\n \tWhen the account holder requests 20\r\n \tThen the ATM should retain the card\r\n \t\tAnd the atm should say the card has been retained\r\n\r\n\r\n##How does BDDfy work?\r\nBDDfy uses quite a few conventions to make it frictionless to use. For your convenience, I will try to provide a quick tutorial below:\r\n\r\n###Finding steps\r\nBDDfy scans your BDDfyed classes for steps. Currently it has three ways of finding a step: \r\n\r\n* Using attributes \r\n* Using method name conventions \r\n* And using fluent API.\r\n\r\nBDDfy runs your steps in the following order: SetupState, ConsecutiveSetupState, Transition, ConsecutiveTransition, Assertion, ConsecutiveAssertion and TearDown. Some of these steps are reported in the console and html reports and some of them are not. Please read below for further information.\r\n\r\n###Attributes\r\nBDDfy looks for a custom attribute called ExecutableAttribute on your method. To make it easier to use, ExecutableAttribute has a few subclasses that you can use: you may apply Given, AndGiven, When, AndWhen, Then, and AndThen attributes on any method you want to make available to BDDfy.\r\n\r\n###Method name convention\r\nBDDfy uses some conventions to find methods that should be turned into steps. Here is the current conventions. The method name:\r\n\r\n* ending with \"Context\" is considered as a setup method (not reported).\r\n* \"Setup\" is considered as as setup method (not reported). \r\n* starting with \"Given\" is considered as a setup method (reported). \r\n* starting with \"AndGiven\" is considered as a setup method that runs after Context, Setup and Given steps reported).\r\n* starting with \"When\" is considered as a transition method (reported). \r\n* starting with \"AndWhen\" is considered as a transition method that runs after When steps (reported).\r\n* starting with \"Then\" is considered as an asserting method (reported).\r\n* starting with \"And\" is considered as an asserting method (reported).\r\n* starting with \"TearDown\" is considered as a finally method which is run after all the other steps (not reported).\r\n\r\nAs you see in the above example you can mix and match the executable attributes and method name conventions to acheive great flexibility and power.\r\n\r\n###Fluent API\r\nFluent API gives you the absolute power over step selection and their titles. When you use Fluent API for a test, the attributes and method name conventions are ignored for that test. \r\n\r\nPlease note that you can have some tests using fluent API and some using a combination of attributes and method name conventions. Each .BDDfy() test works in isolation of others.\r\n\r\n###Other conventions\r\nBDDfy prefers convention over configuration; but it also allows you to configure pretty much all the conventions. \r\n\r\n## Authors and Contributors\r\nMehdi Khalili (@MehdiK), Michael Whelan (@mwhelan)","name":"BDDfy"}
\ No newline at end of file
diff --git a/readme.md b/readme.md
deleted file mode 100644
index 10ad5c22..00000000
--- a/readme.md
+++ /dev/null
@@ -1,132 +0,0 @@
-BDDfy is the simplest BDD framework to use, customize and extend!
-
-A few quick facts about BDDfy:
- - It can run with any testing framework. Actually you don't have to use a testing framework at all. You can just apply it on your POCO (test) classes!
- - It does not need a separate test runner. You can use your runner of choice. For example, you can write your BDDfy tests using NUnit and run them using NUnit console or GUI runner, Resharper or TD.Net and regardless of the runner, you will get the same result.
- - It can run standalone scenarios. In other words, although BDDfy supports stories, you do not necessarily have to have or make up a story to use it. This is useful for developers who work in non-Agile environments but would like to get some decent testing experience.
- - You can use underscored or pascal or camel cased method names for your steps.
- - You do not have to explain your scenarios or stories or steps in string, but you can if you need full control over what gets printed into console and HTML reports.
- - BDDfy is very extensible: the core barely has any logic in it and delegates all its responsibilities to the extensions all of which are configurable; e.g. if you don't like the reports it generates, you can write your custom reporter in a few lines of code.
-
-## Usage
-
-[](https://gitter.im/TestStack/TestStack.BDDfy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-To use BDDfy install TestStack.BDDfy nuget package: `Install-Package TestStack.BDDfy`
-
-This adds BDDfy assembly and its dependencies to your test project. If this is the first time you are using BDDfy you may want to check out the samples on NuGet. Just run `Install-Package TestStack.BDDfy.Samples` and it will load two fully working samples to your project.
-
-Now that you have installed BDDfy, write your first test (this test is borrowed from ATM sample that you can install using nuget package TestStack.BDDfy.Samples):
-
-````csharp
- [Story(
- AsA = "As an Account Holder",
- IWant = "I want to withdraw cash from an ATM",
- SoThat = "So that I can get money when the bank is closed")]
- public class AccountHasInsufficientFund
- {
- private Card _card;
- private Atm _atm;
-
- // You can override step text using executable attributes
- [Given(StepText = "Given the account balance is $10")]
- void GivenAccountHasEnoughBalance()
- {
- _card = new Card(true, 10);
- }
-
- void AndGivenTheCardIsValid()
- {
- }
-
- void AndGivenTheMachineContainsEnoughMoney()
- {
- _atm = new Atm(100);
- }
-
- void WhenTheAccountHolderRequests20()
- {
- _atm.RequestMoney(_card, 20);
- }
-
- void ThenTheAtmShouldNotDispenseAnyMoney()
- {
- Assert.AreEqual(0, _atm.DispenseValue);
- }
-
- void AndTheAtmShouldSayThereAreInsufficientFunds()
- {
- Assert.AreEqual(DisplayMessage.InsufficientFunds, _atm.Message);
- }
-
- void AndTheCardShouldBeReturned()
- {
- Assert.IsFalse(_atm.CardIsRetained);
- }
-
- [Fact]
- public void Execute()
- {
- this.BDDfy();
- }
- }
-````
-
-And this gives you a report like:
-
- Story: Account holder withdraws cash
- As an Account Holder
- I want to withdraw cash from an ATM
- So that I can get money when the bank is closed
-
- Scenario: Account has insufficient fund
- Given the account balance is $10
- And the card is valid
- When the account holder requests $20
- Then the atm should not dispense any money
- And the atm should say there are insufficient funds
- And the card should be returned
-
-This is just the console report. Have a look at your output folder and you should see a nice html report too.
-
-If you want more control you can also use BDDfy's Fluent API. Here is another example done using the Fluent API:
-
-````csharp
- [Fact]
- public void CardHasBeenDisabled()
- {
- this.Given(s => s.GivenTheCardIsDisabled())
- .When(s => s.WhenTheAccountHolderRequests(20))
- .Then(s => s.CardIsRetained(true), "Then the ATM should retain the card")
- .And(s => s.AndTheAtmShouldSayTheCardHasBeenRetained())
- .BDDfy(htmlReportName: "ATM");
- }
-````
-
-which gives you a report like:
-
- Scenario: Card has been disabled
- Given the card is disabled
- When the account holder requests 20
- Then the ATM should retain the card
- And the atm should say the card has been retained
-
-## IDE annotations
-
-This repository contains a small set of in-repo code-analysis annotations (see `src/TestStack.BDDfy/Properties/Annotations.cs`).
-
-Notably, the attribute classes used for step discovery (for example `ExecutableAttribute` and the GWT attribute variants) are marked with a local `MeansImplicitUse` attribute. That makes methods decorated with `[Executable]` (or `[Given]`, `[When]`, `[Then]`, etc.) be treated as "used implicitly" by IDEs such as ReSharper or Rider. The effect: you won't see "unused" inspections on step methods even though they're invoked via reflection at runtime.
-
-If you prefer to use the official `JetBrains.Annotations` NuGet package instead of the in-repo annotations, you can replace the local attributes and add the package as a development-only dependency (use `PrivateAssets="all"` on the package reference so it doesn't become transitive).
-
-
-This is only the tip of iceberg. Absolutely everything you do with BDDfy is extensible and customizable.
-You might see full documentation of BDDfy on the [TestStack documentation website](http://bddfy.teststack.net/).
-Oh and while you are there don't forget to checkout other cool projects from [TestStack](http://www.teststack.net/).
-
-## Authors
-* [Mehdi Khalili](https://github.com/MehdiK)
-* [Michael Whelan](https://github.com/mwhelan)
-* [Jake Ginnivan](https://github.com/JakeGinnivan)
-
-## License
-BDDfy is released under the MIT License. See the bundled license.txt file for details.
\ No newline at end of file
diff --git a/src/.editorconfig b/src/.editorconfig
deleted file mode 100644
index dd2b5504..00000000
--- a/src/.editorconfig
+++ /dev/null
@@ -1,4 +0,0 @@
-[*.cs]
-
-# Default severity for analyzer diagnostics with category 'Style'
-dotnet_analyzer_diagnostic.category-Style.severity = none
diff --git a/src/Directory.build.props b/src/Directory.build.props
deleted file mode 100644
index 19bc63e5..00000000
--- a/src/Directory.build.props
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- net8.0
-
-
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/AssemblySetupFixture.cs b/src/Samples/TestStack.BDDfy.Samples/AssemblySetupFixture.cs
deleted file mode 100644
index 8d2aa259..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/AssemblySetupFixture.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Threading;
-using System.Threading.Tasks;
-using TestStack.BDDfy.Configuration;
-using TestStack.BDDfy.Reporters.Html;
-using TestStack.BDDfy.Samples;
-using TestStack.BDDfy.Samples.Atm;
-using Xunit.Abstractions;
-using Xunit.Sdk;
-
-// The custom test framework enables the support
-[assembly: Xunit.TestFramework("TestStack.BDDfy.Samples.XunitTestFrameworkWithAssemblyFixture", "TestStack.BDDfy.Samples")]
-
-// Add one of these for every fixture classes for the assembly.
-// Just like other fixtures, you can implement IDisposable and it'll
-// get cleaned up at the end of the test run.
-[assembly: AssemblyFixture(typeof(AssemblySetupFixture))]
-
-namespace TestStack.BDDfy.Samples
-{
- public class AssemblySetupFixture
- {
- public AssemblySetupFixture()
- {
- Configurator.Processors.Add(() => new CustomTextReporter());
- Configurator.BatchProcessors.MarkDownReport.Enable();
- Configurator.BatchProcessors.DiagnosticsReport.Enable();
- Configurator.BatchProcessors.Add(new HtmlReporter(new AtmHtmlReportConfig(), new MetroReportBuilder()));
- }
- }
-
- [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
- public class AssemblyFixtureAttribute(Type fixtureType): Attribute
- {
- public Type FixtureType { get; private set; } = fixtureType;
- }
-
- public class XunitTestFrameworkWithAssemblyFixture(IMessageSink messageSink): XunitTestFramework(messageSink)
- {
- protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName)
- => new XunitTestFrameworkExecutorWithAssemblyFixture(assemblyName, SourceInformationProvider, DiagnosticMessageSink);
- }
-
- public class XunitTestFrameworkExecutorWithAssemblyFixture(AssemblyName assemblyName,
- ISourceInformationProvider sourceInformationProvider, IMessageSink diagnosticMessageSink):
- XunitTestFrameworkExecutor(assemblyName, sourceInformationProvider, diagnosticMessageSink)
- {
- protected override async void RunTestCases(IEnumerable testCases,
- IMessageSink executionMessageSink, ITestFrameworkExecutionOptions executionOptions)
- {
- using var assemblyRunner = new XunitTestAssemblyRunnerWithAssemblyFixture(TestAssembly, testCases,
- DiagnosticMessageSink, executionMessageSink, executionOptions);
- await assemblyRunner.RunAsync();
- }
- }
-
- public class XunitTestAssemblyRunnerWithAssemblyFixture(ITestAssembly testAssembly,
- IEnumerable testCases,
- IMessageSink diagnosticMessageSink,
- IMessageSink executionMessageSink,
- ITestFrameworkExecutionOptions executionOptions):
- XunitTestAssemblyRunner(testAssembly, testCases, diagnosticMessageSink, executionMessageSink, executionOptions)
- {
- readonly Dictionary assemblyFixtureMappings = new();
-
- protected override async Task AfterTestAssemblyStartingAsync()
- {
- // Let everything initialize
- await base.AfterTestAssemblyStartingAsync();
-
- // Go find all the AssemblyFixtureAttributes adorned on the test assembly
- Aggregator.Run(() =>
- {
- var fixturesAttrs = ((IReflectionAssemblyInfo)TestAssembly.Assembly).Assembly
- .GetCustomAttributes(typeof(AssemblyFixtureAttribute))
- .Cast()
- .ToList();
-
- // Instantiate all the fixtures
- foreach (var fixtureAttr in fixturesAttrs)
- assemblyFixtureMappings[fixtureAttr.FixtureType] = Activator.CreateInstance(fixtureAttr.FixtureType);
- });
- }
-
- protected override Task BeforeTestAssemblyFinishedAsync()
- {
- // Make sure we clean up everybody who is disposable, and use Aggregator.Run to isolate Dispose failures
- foreach (var disposable in assemblyFixtureMappings.Values.OfType())
- Aggregator.Run(disposable.Dispose);
-
- return base.BeforeTestAssemblyFinishedAsync();
- }
-
- protected override Task RunTestCollectionAsync(IMessageBus messageBus,
- ITestCollection testCollection,
- IEnumerable testCases,
- CancellationTokenSource cancellationTokenSource)
- => new XunitTestCollectionRunnerWithAssemblyFixture(
- assemblyFixtureMappings,
- testCollection,
- testCases,
- DiagnosticMessageSink,
- messageBus,
- TestCaseOrderer,
- new ExceptionAggregator(Aggregator),
- cancellationTokenSource).RunAsync();
- }
-
- public class XunitTestCollectionRunnerWithAssemblyFixture(Dictionary assemblyFixtureMappings,
- ITestCollection testCollection,
- IEnumerable testCases,
- IMessageSink diagnosticMessageSink,
- IMessageBus messageBus,
- ITestCaseOrderer testCaseOrderer,
- ExceptionAggregator aggregator,
- CancellationTokenSource cancellationTokenSource):
- XunitTestCollectionRunner(testCollection, testCases, diagnosticMessageSink, messageBus, testCaseOrderer, aggregator, cancellationTokenSource)
- {
- readonly Dictionary assemblyFixtureMappings = assemblyFixtureMappings;
- readonly IMessageSink diagnosticMessageSink = diagnosticMessageSink;
-
- protected override Task RunTestClassAsync(ITestClass testClass, IReflectionTypeInfo @class, IEnumerable testCases)
- {
- // Don't want to use .Concat + .ToDictionary because of the possibility of overriding types,
- // so instead we'll just let collection fixtures override assembly fixtures.
- var combinedFixtures = new Dictionary(assemblyFixtureMappings);
- foreach (var kvp in CollectionFixtureMappings)
- combinedFixtures[kvp.Key] = kvp.Value;
-
- // We've done everything we need, so let the built-in types do the rest of the heavy lifting
- return new XunitTestClassRunner(
- testClass,
- @class,
- testCases,
- diagnosticMessageSink,
- MessageBus,
- TestCaseOrderer,
- new ExceptionAggregator(Aggregator),
- CancellationTokenSource,
- combinedFixtures).RunAsync();
- }
- }
-
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHasInsufficientFund.cs b/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHasInsufficientFund.cs
deleted file mode 100644
index e9e2a205..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHasInsufficientFund.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Samples.Atm
-{
- public class AccountHasInsufficientFund
- {
- private Card _card;
- private Atm _atm;
-
- // You can override step text using executable attributes
- [Given("Given the Account Balance is $10")]
- void GivenTheAccountBalanceIs10()
- {
- _card = new Card(true, 10);
- }
-
- void And_given_the_Card_is_valid()
- {
- }
-
- void AndGivenTheMachineContainsEnoughMoney()
- {
- _atm = new Atm(100);
- }
-
- [When("When the Account Holder requests $20")]
- void WhenTheAccountHolderRequests20()
- {
- _atm.RequestMoney(_card, 20);
- }
-
- void Then_the_ATM_should_not_dispense_any_Money()
- {
- _atm.DispenseValue.ShouldBe(0);
- }
-
- void And_the_ATM_should_say_there_are_Insufficient_Funds()
- {
- _atm.Message.ShouldBe(DisplayMessage.InsufficientFunds);
- }
-
- [AndThen("And the Account Balance should be $20")]
- void AndTheAccountBalanceShouldBe20()
- {
- _card.AccountBalance.ShouldBe(10);
- }
-
- void And_the_Card_should_be_returned()
- {
- _atm.CardIsRetained.ShouldBe(false);
- }
-
- [Fact]
- public void Verify()
- {
- this.BDDfy();
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHolderWithdrawsCash.cs b/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHolderWithdrawsCash.cs
deleted file mode 100644
index a31fb495..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHolderWithdrawsCash.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Samples.Atm
-{
- [Story(
- AsA = "As an Account Holder",
- IWant = "I want to withdraw cash from an ATM",
- SoThat = "So that I can get money when the bank is closed",
- ImageUri = "https://upload.wikimedia.org/wikipedia/commons/d/d3/49024-SOS-ATM.JPG",
- StoryUri = "http://google.com")]
- public class AccountHolderWithdrawsCash
- {
- private const string GivenTheAccountBalanceIsTitleTemplate = "Given the account balance is ${0}";
- private const string AndTheMachineContainsEnoughMoneyTitleTemplate = "And the machine contains enough money";
- private const string WhenTheAccountHolderRequestsTitleTemplate = "When the account holder requests ${0}";
- private const string AndTheCardShouldBeReturnedTitleTemplate = "And the card should be returned";
-
- private Card _card;
- private Atm _atm;
-
- internal void Given_the_Account_Balance_is(int balance)
- {
- _card = new Card(true, balance);
- }
-
- internal void Given_the_Card_is_disabled()
- {
- _card = new Card(false, 100);
- _atm = new Atm(100);
- }
-
- internal void And_the_Card_is_valid()
- {
- }
-
- internal void And_the_machine_contains(int atmBalance)
- {
- _atm = new Atm(atmBalance);
- }
-
- internal void When_the_Account_Holder_requests(int moneyRequest)
- {
- _atm.RequestMoney(_card, moneyRequest);
- }
-
- internal void The_ATM_should_dispense(int dispensedMoney)
- {
- _atm.DispenseValue.ShouldBe(dispensedMoney);
- }
-
- internal void And_the_Account_Balance_should_be(int balance)
- {
- _card.AccountBalance.ShouldBe(balance);
- }
-
- internal void Then_Card_is_retained(bool cardIsRetained)
- {
- _atm.CardIsRetained.ShouldBe(cardIsRetained);
- }
-
- internal void And_the_ATM_should_say_the_Card_has_been_retained()
- {
- _atm.Message.ShouldBe(DisplayMessage.CardIsRetained);
- }
-
- [Fact]
- public void AccountHasSufficientFund()
- {
- this.Given(s => s.Given_the_Account_Balance_is(100), GivenTheAccountBalanceIsTitleTemplate)
- .And(s => s.And_the_Card_is_valid())
- .And(s => s.And_the_machine_contains(100), AndTheMachineContainsEnoughMoneyTitleTemplate)
- .When(s => s.When_the_Account_Holder_requests(20), WhenTheAccountHolderRequestsTitleTemplate)
- .Then(s => s.The_ATM_should_dispense(20), "Then the ATM should dispense $20")
- .And(s => s.And_the_Account_Balance_should_be(80), "And the account balance should be $80")
- .And(s => s.Then_Card_is_retained(false), AndTheCardShouldBeReturnedTitleTemplate)
- .BDDfy();
- }
-
- [Fact]
- public void CardHasBeenDisabled()
- {
- this.Given(s => s.Given_the_Card_is_disabled())
- .When(s => s.When_the_Account_Holder_requests(20))
- .Then(s => s.Then_Card_is_retained(true), false) // in here I am telling the fluent API that I do not want it to include the input arguments in the step title
- .And(s => s.And_the_ATM_should_say_the_Card_has_been_retained())
- .BDDfy();
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/Atm/Atm.cs b/src/Samples/TestStack.BDDfy.Samples/Atm/Atm.cs
deleted file mode 100644
index ede74525..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/Atm/Atm.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-namespace TestStack.BDDfy.Samples.Atm
-{
- public class Atm(int existingCash)
- {
- public int ExistingCash { get; private set; } = existingCash;
-
- public void RequestMoney(Card card, int request)
- {
- if (!card.Enabled)
- {
- CardIsRetained = true;
- Message = DisplayMessage.CardIsRetained;
- return;
- }
-
- if(card.AccountBalance < request)
- {
- Message = DisplayMessage.InsufficientFunds;
- return;
- }
-
- DispenseValue = request;
- card.AccountBalance -= request;
- }
-
- public int DispenseValue { get; set; }
-
- public bool CardIsRetained { get; private set; }
-
- public DisplayMessage Message { get; private set; }
- }
-
- public class Card(bool enabled, int accountBalance)
- {
- public int AccountBalance { get; set; } = accountBalance;
- private readonly bool _enabled = enabled;
-
- public bool Enabled
- {
- get { return _enabled; }
- }
- }
-
- public enum DisplayMessage
- {
- None = 0,
- CardIsRetained,
- InsufficientFunds
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/Atm/AtmHtmlReportConfig.cs b/src/Samples/TestStack.BDDfy.Samples/Atm/AtmHtmlReportConfig.cs
deleted file mode 100644
index 25f93568..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/Atm/AtmHtmlReportConfig.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-using System;
-using TestStack.BDDfy.Reporters.Html;
-
-namespace TestStack.BDDfy.Samples.Atm
-{
- ///
- /// This overrides the default html report setting
- ///
- public class AtmHtmlReportConfig : DefaultHtmlReportConfiguration
- {
- public override bool RunsOn(Story story)
- {
- return story.Namespace.EndsWith("Atm", StringComparison.OrdinalIgnoreCase);
- }
-
- ///
- /// Change the output file name
- ///
- public override string OutputFileName
- {
- get
- {
- return "ATM.html";
- }
- }
-
- ///
- /// Change the report header to your project
- ///
- public override string ReportHeader
- {
- get
- {
- return "ATM Solutions";
- }
- }
-
- ///
- /// Change the report description
- ///
- public override string ReportDescription
- {
- get
- {
- return "A reliable solution for your offline banking needs";
- }
- }
-
- ///
- /// For ATM report I want to embed jQuery in the report so people can see it with no internet connectivity
- ///
- public override bool ResolveJqueryFromCdn
- {
- get { return false; }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/BDDfy_Rocks.cs b/src/Samples/TestStack.BDDfy.Samples/BDDfy_Rocks.cs
deleted file mode 100644
index ca788f65..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/BDDfy_Rocks.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using Xunit;
-
-namespace TestStack.BDDfy.Samples
-{
- [Story(
- AsA = "As a .Net programmer",
- IWant = "I want to use BDDfy",
- SoThat = "So that BDD becomes easy and fun",
- ImageUri = "https://upload.wikimedia.org/wikipedia/commons/7/72/DirkvdM_rocks.jpg",
- StoryUri = "https://en.wikipedia.org/wiki/Rock_%28geology%29")]
- public class BDDfy_Rocks
- {
- void Given_I_have_not_used_BDDfy_before()
- {
- }
-
- void WhenIAmIntroducedToTheFramework()
- {
- }
-
- void ThenILikeItAndStartUsingIt()
- {
- }
-
- void AndTheQualityAndMaintainabilityOfMyTestSkyrocket()
- {
- }
-
- [Fact]
- public void BDDfy_with_reflective_API()
- {
- this.BDDfy();
- }
-
- [Fact]
- public void BDDfy_with_fluent_API()
- {
- this.Given(_ => Given_I_have_not_used_BDDfy_before())
- .When(_ => WhenIAmIntroducedToTheFramework())
- .Then(_ => ThenILikeItAndStartUsingIt())
- .And(_ => AndTheQualityAndMaintainabilityOfMyTestSkyrocket())
- .BDDfy();
- }
- }
-}
diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFareWithExamples.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFareWithExamples.cs
deleted file mode 100644
index 9a0a9c4c..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFareWithExamples.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using TestStack.BDDfy.Samples.BuyingTrainFares;
-using Xunit;
-
-namespace TestStack.BDDfy.Samples
-{
- public class BuyingTrainFareWithExamples
- {
- #pragma warning disable 649
- // ReSharper disable once InconsistentNaming
- private Fare fare;
- private BuyerCategory _buyerCategory;
- #pragma warning restore 649
- Money Price { get; set; }
-
- [Fact]
- public void SuccessfulRailCardPurchases()
- {
- this.Given(_ => TheBuyerIsA(_buyerCategory))
- .And(_ => TheBuyerSelectsA(fare))
- .When(_ => TheBuyerPays())
- .Then(_ => ASaleOccursWithAnAmountOf(Price))
- .WithExamples(new ExampleTable(
- "Buyer Category", "Fare", "Price")
- {
- {BuyerCategory.Student, new MonthlyPass(), new Money(76)},
- {BuyerCategory.Senior, new MonthlyPass(), new Money(98)},
- {BuyerCategory.Standard, new MonthlyPass(), new Money(146)},
- {BuyerCategory.Student, new WeeklyPass(), new Money(23)},
- {BuyerCategory.Senior, new WeeklyPass(), new Money(30)},
- {BuyerCategory.Standard, new WeeklyPass(), new Money(44)},
- {BuyerCategory.Student, new DayPass(), new Money(4)},
- {BuyerCategory.Senior, new DayPass(), new Money(5)},
- {BuyerCategory.Standard, new DayPass(), new Money(7)},
- {BuyerCategory.Student, new SingleTicket(), new Money(1.5m)},
- {BuyerCategory.Senior, new SingleTicket(), new Money(2m)},
- {BuyerCategory.Standard, new SingleTicket(), new Money(3m)}
- })
- .BDDfy("Successful rail card purchases");
- }
-
- void TheBuyerIsA(BuyerCategory buyerCategory)
- {
-
- }
-
- void TheBuyerSelectsA(Fare fare)
- {
-
- }
-
- void TheBuyerPays()
- {
-
- }
-
- void ASaleOccursWithAnAmountOf(Money price)
- {
-
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/BuyerCategory.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/BuyerCategory.cs
deleted file mode 100644
index b78f699c..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/BuyerCategory.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace TestStack.BDDfy.Samples.BuyingTrainFares
-{
- enum BuyerCategory
- {
- Student,
- Senior,
- Standard
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/DayPass.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/DayPass.cs
deleted file mode 100644
index 22f5f5cf..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/DayPass.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace TestStack.BDDfy.Samples.BuyingTrainFares
-{
- class DayPass : Fare
- {
- public override string ToString()
- {
- return "Day Pass";
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Fare.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Fare.cs
deleted file mode 100644
index a397dab3..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Fare.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace TestStack.BDDfy.Samples.BuyingTrainFares
-{
- class Fare
- {
-
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Money.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Money.cs
deleted file mode 100644
index b032fa3d..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Money.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System.Globalization;
-
-namespace TestStack.BDDfy.Samples.BuyingTrainFares
-{
- class Money(decimal amount)
- {
- public decimal Amount { get; set; } = amount;
-
- protected bool Equals(Money other)
- {
- return Amount == other.Amount;
- }
-
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- if (obj.GetType() != GetType()) return false;
- return Equals((Money)obj);
- }
-
- public override int GetHashCode()
- {
- return Amount.GetHashCode();
- }
-
- public static bool operator ==(Money left, Money right)
- {
- return Equals(left, right);
- }
-
- public static bool operator !=(Money left, Money right)
- {
- return !Equals(left, right);
- }
-
- public override string ToString()
- {
- return Amount.ToString("C", new CultureInfo("EN-US"));
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/MonthlyPass.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/MonthlyPass.cs
deleted file mode 100644
index 09ac243b..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/MonthlyPass.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace TestStack.BDDfy.Samples.BuyingTrainFares
-{
- class MonthlyPass : Fare
- {
- public override string ToString()
- {
- return "Monthly Pass";
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/SingleTicket.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/SingleTicket.cs
deleted file mode 100644
index 60ca4eaf..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/SingleTicket.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace TestStack.BDDfy.Samples.BuyingTrainFares
-{
- class SingleTicket : Fare
- {
- public override string ToString()
- {
- return "Day Pass";
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/WeeklyPass.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/WeeklyPass.cs
deleted file mode 100644
index fc9a511e..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/WeeklyPass.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace TestStack.BDDfy.Samples.BuyingTrainFares
-{
- class WeeklyPass : Fare
- {
- public override string ToString()
- {
- return "Weekly Pass";
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs b/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs
deleted file mode 100644
index 1025b3a3..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System;
-using System.Threading.Tasks;
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Samples
-{
- public class CanRunAsyncSteps
- {
- private Sut _sut;
-
- internal async void GivenSomeAsyncSetup()
- {
- _sut = await CreateSut();
- }
-
- internal void ThenBddfyHasWaitedForThatSetupToCompleteBeforeContinuing()
- {
- _sut.ShouldNotBe(null);
- }
-
- internal async Task AndThenBddfyShouldCaptureExceptionsThrownInAsyncMethod()
- {
- await Task.Yield();
- throw new Exception("Exception in async void method!!");
- }
-
- private async Task CreateSut()
- {
- await Task.Delay(500);
- return new Sut();
- }
-
- [Fact]
- public void Run()
- {
- var engine = this.LazyBDDfy();
- var exception = Should.Throw(() => engine.Run());
-
- exception.Message.ShouldBe("Exception in async void method!!");
- }
-
- internal class Sut
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs b/src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs
deleted file mode 100644
index ac41d335..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using Xunit;
-
-namespace TestStack.BDDfy.Samples
-{
- public class CanWorkWithoutAStory
- {
- internal void Given_no_story_is_provided()
- {
- }
-
- internal void When_we_BDDfy_the_class()
- {
- }
-
- internal void Then_the_namespace_is_used_in_the_report()
- {
- }
-
- [Fact]
- public void Execute()
- {
- this.BDDfy();
- }
- }
-}
diff --git a/src/Samples/TestStack.BDDfy.Samples/CustomTextReporter.cs b/src/Samples/TestStack.BDDfy.Samples/CustomTextReporter.cs
deleted file mode 100644
index 5293448a..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/CustomTextReporter.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using System;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-
-namespace TestStack.BDDfy.Samples
-{
- ///
- /// This is a custom reporter that shows you how easily you can create a custom report.
- /// Just implemented IProcessor and you are done
- ///
- public class CustomTextReporter : IProcessor
- {
- private static readonly string Path;
-
- private static string OutputDirectory
- {
- get
- {
- string codeBase = typeof(CustomTextReporter).GetTypeInfo().Assembly.Location;
- return System.IO.Path.GetDirectoryName(codeBase);
- }
- }
-
- static CustomTextReporter()
- {
- Path = System.IO.Path.Combine(OutputDirectory, "BDDfy-text-report.txt");
-
- if(File.Exists(Path))
- File.Delete(Path);
-
- var header =
- " A custom report created from your test assembly with no required configuration " +
- Environment.NewLine +
- Environment.NewLine +
- Environment.NewLine +
- Environment.NewLine;
- File.AppendAllText(Path, header);
- }
-
- public void Process(Story story)
- {
- // use this report only for tic tac toe stories
- if (story.Metadata == null || !story.Metadata.Type.Name.Contains("TicTacToe"))
- return;
-
- var scenario = story.Scenarios.First();
- var scenarioReport = new StringBuilder();
- scenarioReport.AppendLine(string.Format(" SCENARIO: {0} ", scenario.Title));
-
- if (scenario.Result != Result.Passed && scenario.Steps.Any(s => s.Exception != null))
- {
- scenarioReport.Append(string.Format(" {0} : ", scenario.Result));
- scenarioReport.AppendLine(scenario.Steps.First(s => s.Result == scenario.Result).Exception.Message);
- }
-
- scenarioReport.AppendLine();
-
- foreach (var step in scenario.Steps)
- scenarioReport.AppendLine(string.Format(" [{1}] {0}", step.Title, step.Result));
-
- scenarioReport.AppendLine("--------------------------------------------------------------------------------");
- scenarioReport.AppendLine();
-
- File.AppendAllText(Path, scenarioReport.ToString());
- }
-
- public ProcessType ProcessType
- {
- get { return ProcessType.Report; }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj b/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj
deleted file mode 100644
index 8a150d91..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
- net8.0
- TestStack.BDDfy.Samples
- TestStack.BDDfy.Samples
- true
- false
- false
- false
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
diff --git a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Game.cs b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Game.cs
deleted file mode 100644
index 3a9ba31f..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Game.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-
-namespace TestStack.BDDfy.Samples.TicTacToe
-{
- public class Game
- {
- public const string X = "X";
- public const string O = "O";
- public const string N = " ";
-
- private static readonly string[] EmptyRow = Enumerable.Repeat(N, 3).ToArray();
- readonly string[][] _board;
-
- public Game()
- : this(EmptyRow, EmptyRow, EmptyRow)
- {
- }
-
- public Game(string[] firstRow, string[] secondRow, string[] thirdRow)
- {
- _board = new string[3][];
- _board[0] = (string[])firstRow.Clone();
- _board[1] = (string[])secondRow.Clone();
- _board[2] = (string[])thirdRow.Clone();
- }
-
- public string Winner
- {
- get
- {
- var winnerLine = Lines.FirstOrDefault(line => line.All(l => l == X) || line.All(l => l == O));
- if (winnerLine == null)
- return null;
-
- return winnerLine.First();
- }
- }
-
- IEnumerable Lines
- {
- get
- {
- for (int i = 0; i < 3; i++)
- {
- yield return new[] { _board[i][0], _board[i][1], _board[i][2] };
- yield return new[] { _board[0][i], _board[1][i], _board[2][i] };
- }
-
- yield return new[] { _board[0][0], _board[1][1], _board[2][2] };
- yield return new[] { _board[2][0], _board[1][1], _board[0][2] };
- }
- }
-
- public void PlayAt(int row, int column)
- {
- var emptyCellsCount = _board.SelectMany(s=>s).Count(s => s == N);
- var player = X;
- if (emptyCellsCount % 2 == 0)
- player = O;
-
- _board[row][column] = player;
- }
-
- public override bool Equals(object obj)
- {
- var game = obj as Game;
- return game != null && base.Equals(game);
- }
-
- public bool Equals(Game other)
- {
- if (ReferenceEquals(null, other)) return false;
- if (ReferenceEquals(this, other)) return true;
-
- for (int i = 0; i < 3; i++)
- {
- if(!_board[i].SequenceEqual(other._board[i]))
- return false;
- }
-
- return true;
- }
-
- public override int GetHashCode()
- {
- return (_board != null ? _board.GetHashCode() : 0);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Helpers.cs b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Helpers.cs
deleted file mode 100644
index 98d1876c..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Helpers.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using Shouldly;
-
-namespace TestStack.BDDfy.Samples.TicTacToe
-{
- public static class Helpers
- {
- public static void VerifyBoardState(this Game game, string[] firstRow, string[] secondRow, string[] thirdRow)
- {
- game.Equals(new Game(firstRow, secondRow, thirdRow)).ShouldBe(true);
- }
- }
-
- public class GameUnderTest
- {
- protected const string BoardStateTemplate = "Given the board\r\n{0}\r\n{1}\r\n{2}";
-
- protected const string X = Game.X;
- protected const string O = Game.O;
- protected const string N = Game.N;
-
- protected Game Game { get; set; }
- }
-
- public abstract class NewGame : GameUnderTest
- {
- protected void GivenANewGame()
- {
- Game = new Game();
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/TicTacToe.cs b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/TicTacToe.cs
deleted file mode 100644
index 726295a3..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/TicTacToe.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-using Shouldly;
-using Xunit;
-using Xunit.Extensions;
-
-namespace TestStack.BDDfy.Samples.TicTacToe
-{
- [Story(
- AsA = "As a player",
- IWant = "I want to have a tic tac toe game",
- SoThat = "So that I can waste some time!")]
- public class TicTacToe : NewGame
- {
- class Cell(int row, int col)
- {
- public int Row { get; set; } = row;
- public int Col { get; set; } = col;
-
- public override string ToString()
- {
- return string.Format("({0}, {1})", Row, Col);
- }
- }
-
- void GivenTheFollowingBoard(string[] firstRow, string[] secondRow, string[] thirdrow)
- {
- Game = new Game(firstRow, secondRow, thirdrow);
- }
-
- void ThenTheBoardStateShouldBe(string[] firstRow, string[] secondRow, string[] thirdrow)
- {
- Game.VerifyBoardState(firstRow, secondRow, thirdrow);
- }
-
- void ThenTheWinnerShouldBe(string expectedWinner)
- {
- Game.Winner.ShouldBe(expectedWinner);
- }
-
- void ThenItShouldBeACatsGame()
- {
- Game.Winner.ShouldBe(null);
- }
-
- void WhenTheGameIsPlayedAt(params Cell[] cells)
- {
- foreach (var cell in cells)
- {
- Game.PlayAt(cell.Row, cell.Col);
- }
- }
-
- [Fact]
- public void CatsGame()
- {
- this.Given(s => s.GivenTheFollowingBoard(new[] { X, O, X }, new[] { O, O, X }, new[] { X, X, O }), BoardStateTemplate)
- .Then(s => s.ThenItShouldBeACatsGame())
- .BDDfy("Cat's game");
- }
-
- [Fact]
- public void WhenXAndOPlayTheirFirstMoves()
- {
- this.Given(s => s.GivenANewGame())
- .When(s => s.WhenTheGameIsPlayedAt(new Cell(0, 0), new Cell(2, 2)), "When X and O play on {0}")
- .Then(s => s.ThenTheBoardStateShouldBe(new[] { X, N, N }, new[] { N, N, N }, new[] { N, N, O }))
- .BDDfy();
- }
-
- [Fact]
- public void OWins()
- {
- var cell = new Cell(2, 0);
- this.Given(s => s.GivenTheFollowingBoard(new[] { X, X, O }, new[] { X, O, N }, new[] { N, N, N }))
- .When(s => s.WhenTheGameIsPlayedAt(cell))
- .Then(s => s.ThenTheWinnerShouldBe(O))
- .BDDfy();
- }
-
- [Fact]
- public void XWins()
- {
- // This is implemented like this to show you the possibilities
- new XWins().BDDfy();
- }
-
- [Theory]
- [InlineData("Vertical win in the right", new[] { X, O, X }, new[] { O, O, X }, new[] { O, X, X }, X)]
- [InlineData("Vertical win in the middle", new[] { N, X, O }, new[] { O, X, O }, new[] { O, X, X }, X)]
- [InlineData("Diagonal win", new[] { X, O, O }, new[] { X, O, X }, new[] { O, X, N }, O)]
- [InlineData("Horizontal win in the bottom", new[] { X, X, N }, new[] { X, O, X }, new[] { O, O, O }, O)]
- [InlineData("Horizontal win in the middle", new[] { X, O, O }, new[] { X, X, X }, new[] { O, O, X }, X)]
- [InlineData("Vertical win in the left", new[] { X, O, O }, new[] { X, O, X }, new[] { X, X, O }, X)]
- [InlineData("Horizontal win", new[] { X, X, X }, new[] { X, O, O }, new[] { O, O, X }, X)]
- public void WinnerGame(string title, string[] firstRow, string[] secondRow, string[] thirdRow, string expectedWinner)
- {
- new WinnerGame(firstRow, secondRow, thirdRow, expectedWinner).BDDfy(title);
- }
- }
-}
diff --git a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/WinnerGame.cs b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/WinnerGame.cs
deleted file mode 100644
index 43e363eb..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/WinnerGame.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System.Collections.Generic;
-using NUnit.Framework;
-using Shouldly;
-
-namespace TestStack.BDDfy.Samples.TicTacToe
-{
- public class WinnerGame(string[] firstRow, string[] secondRow, string[] thirdRow, string expectedWinner): GameUnderTest
- {
- private readonly string[] _firstRow = firstRow;
- private readonly string[] _secondRow = secondRow;
- private readonly string[] _thirdRow = thirdRow;
- private readonly string _expectedWinner = expectedWinner;
-
- // Note: This method returns IEnumerable
- // this is done to allow the method to return its title.
- // if you use this method make sure to yield return the title as the very first action
- IEnumerable GivenTheFollowingBoard()
- {
- yield return string.Format(
- BoardStateTemplate,
- string.Join(", ", _firstRow),
- string.Join(", ", _secondRow),
- string.Join(", ", _thirdRow));
-
- Game = new Game(_firstRow, _secondRow, _thirdRow);
- }
-
- // Note: This method returns IEnumerable
- // this is done to allow the method to return its title.
- // if you use this method make sure to yield return the title as the very first action
- IEnumerable ThenTheWinnerShouldBe()
- {
- yield return "Then the winner is " + _expectedWinner;
- Game.Winner.ShouldBe(_expectedWinner);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/XWins.cs b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/XWins.cs
deleted file mode 100644
index 304facd2..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/XWins.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Shouldly;
-
-namespace TestStack.BDDfy.Samples.TicTacToe
-{
- public class XWins : GameUnderTest
- {
- [RunStepWithArgs(
- new[] { X, X, O },
- new[] { X, X, O },
- new[] { O, O, N },
- StepTextTemplate = BoardStateTemplate)]
- void GivenTheFollowingBoard(string[] firstRow, string[] secondRow, string[] thirdRow)
- {
- Game = new Game(firstRow, secondRow, thirdRow);
- }
-
- void WhenXPlaysInTheBottomRight()
- {
- Game.PlayAt(2, 2);
- }
-
- void ThenTheWinnerShouldBeX()
- {
- Game.Winner.ShouldBe(X);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Samples/TestStack.BDDfy.Samples/UseExamplesWithFluentApi.cs b/src/Samples/TestStack.BDDfy.Samples/UseExamplesWithFluentApi.cs
deleted file mode 100644
index 19cd6603..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/UseExamplesWithFluentApi.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Samples
-{
- public class UseExamplesWithFluentApi
- {
- public int Start { get; set; }
- public int Eat { get; set; }
- public int Left { get; set; }
-
- [Fact]
- public void RunExamplesWithFluentApi()
- {
- this.Given("Given there are cucumbers")
- .And(_ => _.AndIStealTwoMore())
- .When(_ => _.WhenIEat__eat__Cucumbers())
- .Then(_ => _.ThenIShouldHave__left__Cucumbers())
- .WithExamples(new ExampleTable("Start", "Eat", "Left")
- {
- {12, 5, 9},
- {20, 5, 17}
- })
- .BDDfy();
- }
-
-
- // I didn't have to create this method
- // because all it was going to do was to set Start property
- // which is being handled by the framework
- // And the step title is provided inline
- //private void GivenThereAre__start__Cucumbers()
- //{
- //}
-
- private void AndIStealTwoMore()
- {
- Start += 2;
- }
-
- private void WhenIEat__eat__Cucumbers()
- {
- // This method is called after the Eat property is set by the framework
- // I didn't have to put this here, like the Given method, but I put it here to show that
- // you can take additional actions here if you want
- }
-
- private void ThenIShouldHave__left__Cucumbers()
- {
- (Start - Eat).ShouldBe(Left);
- }
- }
-}
diff --git a/src/Samples/TestStack.BDDfy.Samples/UseExamplesWithReflectiveApi.cs b/src/Samples/TestStack.BDDfy.Samples/UseExamplesWithReflectiveApi.cs
deleted file mode 100644
index 0f1e77e4..00000000
--- a/src/Samples/TestStack.BDDfy.Samples/UseExamplesWithReflectiveApi.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Samples
-{
- public class UseExamplesWithReflectiveApi
- {
- private int _start;
- private int _eat;
-
- [Fact]
- public void CanRunExamplesWithReflectiveApi()
- {
- this.WithExamples(new ExampleTable("Start", "Eat", "Left")
- {
- {12, 5, 7},
- {20, 5, 15}
- })
- .BDDfy();
- }
-
- void GivenThereAre__start__Cucumbers(int start)
- {
- // the start argument is provided by the framework based on the example entries
- // please note that `start` argument name matches the `start` header from the examples
- // and also it has to match with the placeholder in the step title which is created based on conventions
- _start = start;
- }
-
- [AndGiven("And I eat of them")]
- void WhenIEatAFewCucumbers(int eat)
- {
- // the eat argument is provided by the framework based on the example entries
- // please note that `eat` argument name matches the `start` header from the examples
- // and also it has to match the placeholder in the step title
- _eat = eat;
- }
-
- void ThenIShouldHave__left__Cucumbers(int left)
- {
- // like given and when steps left is provided here because it matches the example header and is found on the step title
- (_start - _eat).ShouldBe(left);
- }
- }
-}
diff --git a/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs b/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs
deleted file mode 100644
index cc6bb5a8..00000000
--- a/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-using System.Collections.Generic;
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Arguments
-{
- public class ArgumentsProvidedForGiven
- {
- private readonly List _andGivenInput1 = new();
- private List _andGivenInput2 = new();
- private List _andGivenInput3 = new();
-
- private int _givenInput3;
- private int _givenInput2;
- private int _givenInput1;
-
- [RunStepWithArgs(1, 2, 3)]
- void GivenOneSetOfArgumentsAreProvidedForGivenPart(int input1, int input2, int input3)
- {
- _givenInput1 = input1;
- _givenInput2 = input2;
- _givenInput3 = input3;
- }
-
- [RunStepWithArgs(4, 5, 6)]
- [RunStepWithArgs(7, 8, 9)]
- void GivenMoreThanOneSetOfArgumentsAreProvidedForGivenPart(int input1, int input2, int input3)
- {
- _andGivenInput1.Add(input1);
- _andGivenInput2.Add(input2);
- _andGivenInput3.Add(input3);
- }
-
- void ThenOneSetOfArgumentsArePassedInProperly()
- {
- _givenInput1.ShouldBe(1);
- _givenInput2.ShouldBe(2);
- _givenInput3.ShouldBe(3);
- }
-
- void ThenSeveralSetsOfArgumentsArePassedInProperly()
- {
- _andGivenInput1.Count.ShouldBe(2);
- _andGivenInput1.ShouldContain(4);
- _andGivenInput1.ShouldContain(7);
-
- _andGivenInput2.Count.ShouldBe(2);
- _andGivenInput2.ShouldContain(5);
- _andGivenInput2.ShouldContain(8);
-
- _andGivenInput3.Count.ShouldBe(2);
- _andGivenInput3.ShouldContain(6);
- _andGivenInput3.ShouldContain(9);
- }
-
- [Fact]
- public void Execute()
- {
- this.BDDfy();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForThen.cs b/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForThen.cs
deleted file mode 100644
index 3cbe11b1..00000000
--- a/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForThen.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Arguments
-{
- public class ArgumentsProvidedForThen
- {
- void GivenArgumentsAreProvidedForThenPart()
- {
- }
-
- [RunStepWithArgs(1, "Test")]
- void ThenArgumentsAreSentToThenPart(int argument1, string argument2)
- {
- argument1.ShouldBe(1);
- argument2.ShouldBe("Test");
- }
-
- [Fact]
- public void Execute()
- {
- this.BDDfy();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Arguments/MultipleArgumentsProvidedForTheSameStep.cs b/src/TestStack.BDDfy.Tests/Arguments/MultipleArgumentsProvidedForTheSameStep.cs
deleted file mode 100644
index 893b13c9..00000000
--- a/src/TestStack.BDDfy.Tests/Arguments/MultipleArgumentsProvidedForTheSameStep.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System.Collections.Generic;
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Arguments
-{
- public class MultipleArgumentsProvidedForTheSameStep
- {
- private readonly List _inputs = new();
-
- [RunStepWithArgs(1)]
- [RunStepWithArgs(2)]
- [RunStepWithArgs(3)]
- void GivenMultipleArgumentAttributesAreProvidedToSameMethod(int input)
- {
- _inputs.Add(input);
- }
-
- void ThenTheMethodIsCalledOncePerArgument()
- {
- _inputs.Count.ShouldBe(3);
- _inputs.ShouldContain(1);
- _inputs.ShouldContain(2);
- _inputs.ShouldContain(3);
- }
-
- [Fact]
- public void Execute()
- {
- this.BDDfy();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Concurrency/ParallelRunnerScenario.cs b/src/TestStack.BDDfy.Tests/Concurrency/ParallelRunnerScenario.cs
deleted file mode 100644
index 700e1b7e..00000000
--- a/src/TestStack.BDDfy.Tests/Concurrency/ParallelRunnerScenario.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Linq;
-using System.Threading.Tasks;
-using TestStack.BDDfy.Tests.Stories;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Concurrency
-{
- public class ParallelRunnerScenario
- {
- [Fact]
- public async Task CanHandleMultipleThreadsExecutingBddfyConcurrently()
- {
- await Task.WhenAll(
- Enumerable.Range(0, 100)
- .Select(_ => Task.Run(() => new DummyScenario().BDDfy())));
- }
- }
-}
diff --git a/src/TestStack.BDDfy.Tests/Configuration/BatchProcessorsTests.cs b/src/TestStack.BDDfy.Tests/Configuration/BatchProcessorsTests.cs
deleted file mode 100644
index b6ac86f7..00000000
--- a/src/TestStack.BDDfy.Tests/Configuration/BatchProcessorsTests.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-using System.Linq;
-using Shouldly;
-using TestStack.BDDfy.Configuration;
-using TestStack.BDDfy.Reporters.Html;
-using TestStack.BDDfy.Reporters.MarkDown;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Configuration
-{
- public class BatchProcessorsTests
- {
- static bool MetroReportProcessorIsActive(IBatchProcessor batchProcessor)
- {
- return batchProcessor is HtmlReporter && ((HtmlReporter)batchProcessor).ReportBuilder is MetroReportBuilder;
- }
-
- [Fact]
- public void ReturnsHtmlReporterByDefault()
- {
- var processors = Configurator.BatchProcessors.GetProcessors().ToList();
- processors.Any(p => p is HtmlReporter).ShouldBe(true);
- }
-
- [Fact]
- public void DoesNotReturnMarkDownReporterByDefault()
- {
- var processors = Configurator.BatchProcessors.GetProcessors().ToList();
- processors.Any(p => p is MarkDownReporter).ShouldBe(false);
- }
-
- [Fact]
- public void DoesNotReturnHtmlMetroReporterByDefault()
- {
- var processors = Configurator.BatchProcessors.GetProcessors().ToList();
- processors.Any(MetroReportProcessorIsActive).ShouldBe(false);
- }
-
- [Fact]
- public void DoesNotReturnHtmlReporterWhenItIsDeactivated()
- {
- Configurator.BatchProcessors.HtmlReport.Disable();
-
- var processors = Configurator.BatchProcessors.GetProcessors().ToList();
- processors.Any(p => p is HtmlReporter).ShouldBe(false);
-
- Configurator.BatchProcessors.HtmlReport.Enable();
- }
-
- [Fact]
- public void ReturnsMarkdownReporterWhenItIsActivated()
- {
- Configurator.BatchProcessors.MarkDownReport.Enable();
-
- var processors = Configurator.BatchProcessors.GetProcessors().ToList();
- processors.Any(p => p is MarkDownReporter).ShouldBe(true);
-
- Configurator.BatchProcessors.MarkDownReport.Disable();
- }
-
- [Fact]
- public void ReturnsHtmlMetroReporterWhenItIsActivated()
- {
- Configurator.BatchProcessors.HtmlMetroReport.Enable();
-
- var processors = Configurator.BatchProcessors.GetProcessors().ToList();
- processors.Any(MetroReportProcessorIsActive).ShouldBe(true);
-
- Configurator.BatchProcessors.HtmlMetroReport.Disable();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Configuration/CustomProcessor.cs b/src/TestStack.BDDfy.Tests/Configuration/CustomProcessor.cs
deleted file mode 100644
index 9ebe2edb..00000000
--- a/src/TestStack.BDDfy.Tests/Configuration/CustomProcessor.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace TestStack.BDDfy.Tests.Configuration
-{
- public class CustomProcessor : IProcessor
- {
- public ProcessType ProcessType
- {
- get { return ProcessType.BeforeReport; }
- }
-
- public void Process(Story story)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Configuration/EmptyScenario.cs b/src/TestStack.BDDfy.Tests/Configuration/EmptyScenario.cs
deleted file mode 100644
index afd27c26..00000000
--- a/src/TestStack.BDDfy.Tests/Configuration/EmptyScenario.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace TestStack.BDDfy.Tests.Configuration
-{
- public class EmptyScenario
- {
- public void GivenSomething() { }
- public void WhenSomething() { }
- public void ThenSomething() { }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Configuration/ProcessorPipelineTests.cs b/src/TestStack.BDDfy.Tests/Configuration/ProcessorPipelineTests.cs
deleted file mode 100644
index 3ca8a1ab..00000000
--- a/src/TestStack.BDDfy.Tests/Configuration/ProcessorPipelineTests.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using System.Linq;
-using Shouldly;
-using TestStack.BDDfy.Configuration;
-using TestStack.BDDfy.Processors;
-using TestStack.BDDfy.Reporters;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Configuration
-{
- [Collection("ExclusiveAccessToConfigurator")]
- public class ProcessorPipelineTests
- {
- [Fact]
- public void ReturnsDefaultPipelineByDefault()
- {
- var processors = Configurator.Processors.GetProcessors(new Story(null)).ToList();
-
- processors.Any(p => p is ConsoleReporter).ShouldBe(true);
- processors.Any(p => p is StoryCache).ShouldBe(true);
- processors.Any(p => p is TestRunner).ShouldBe(true);
- processors.Any(p => p is ExceptionProcessor).ShouldBe(true);
- }
-
- [Fact]
- public void DoesNotReturnConsoleReportWhenItIsDeactivated()
- {
- Configurator.Processors.ConsoleReport.Disable();
- var processors = Configurator.Processors.GetProcessors(new Story(null)).ToList();
-
- processors.Any(p => p is ConsoleReporter).ShouldBe(false);
- processors.Any(p => p is StoryCache).ShouldBe(true);
- processors.Any(p => p is TestRunner).ShouldBe(true);
- processors.Any(p => p is ExceptionProcessor).ShouldBe(true);
- Configurator.Processors.ConsoleReport.Enable();
- }
-
- [Fact]
- public void DoesNotReturnConsoleReportForExcludedStories()
- {
- Configurator.Processors.ConsoleReport.RunsOn(s => s.Metadata != null);
- var processors = Configurator.Processors.GetProcessors(new Story(null)).ToList();
-
- processors.Any(p => p is ConsoleReporter).ShouldBe(false);
- Configurator.Processors.ConsoleReport.RunsOn(s => true);
- }
-
- [Fact]
- public void DoesNotReturnTestRunnerWhenItIsDeactivated()
- {
- Configurator.Processors.TestRunner.Disable();
- var processors = Configurator.Processors.GetProcessors(new Story(null)).ToList();
-
- processors.Any(p => p is ConsoleReporter).ShouldBe(true);
- processors.Any(p => p is TestRunner).ShouldBe(false);
- processors.Any(p => p is StoryCache).ShouldBe(true);
- processors.Any(p => p is ExceptionProcessor).ShouldBe(true);
- Configurator.Processors.TestRunner.Enable();
- }
-
- [Fact]
- public void CanAddCustomProcessor()
- {
- var processors = Configurator
- .Processors
- .Add(() => new CustomProcessor())
- .GetProcessors(new Story(null)).ToList();
-
- processors.Any(p => p is CustomProcessor).ShouldBe(true);
- processors.Any(p => p is StoryCache).ShouldBe(true);
- processors.Any(p => p is ConsoleReporter).ShouldBe(true);
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Configuration/SequentialKeyGeneratorTests.cs b/src/TestStack.BDDfy.Tests/Configuration/SequentialKeyGeneratorTests.cs
deleted file mode 100644
index ad2501cd..00000000
--- a/src/TestStack.BDDfy.Tests/Configuration/SequentialKeyGeneratorTests.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using Shouldly;
-using TestStack.BDDfy.Configuration;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Configuration
-{
- public class SequentialKeyGeneratorTests
- {
- [Fact]
- public void ShouldReturnOneForFirstScenario()
- {
- new SequentialKeyGenerator().GetScenarioId().ShouldBe("scenario-1");
- }
-
- [Fact]
- public void ShouldIncrementScenarioIdForEachRequestForScenariId()
- {
- var sut = new SequentialKeyGenerator();
-
- for (int i = 1; i <= 12; i++)
- {
- sut.GetScenarioId().ShouldBe("scenario-" + i);
- }
- }
-
- [Fact]
- public void ShouldReturnOneOneForFirstStepOfFirstScenario()
- {
- new SequentialKeyGenerator().GetStepId().ShouldBe("step-1-1");
- }
-
- [Fact]
- public void ShouldIncrementStepIdForEachRequestForStepId()
- {
- var sut = new SequentialKeyGenerator();
-
- for (int i = 1; i <= 12; i++)
- {
- sut.GetStepId().ShouldBe("step-1-" + i);
- }
- }
-
- [Fact]
- public void ShouldResetStepCountForNewScenario()
- {
- var sut = new SequentialKeyGenerator();
- sut.GetStepId();
- sut.GetScenarioId();
-
- sut.GetStepId().ShouldBe("step-2-1");
- }
- }
-}
diff --git a/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs b/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs
deleted file mode 100644
index 8d9e1916..00000000
--- a/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-using System.Text;
-using Shouldly;
-using TestStack.BDDfy.Configuration;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Configuration
-{
- [Collection("ExclusiveAccessToConfigurator")]
- public class StepExecutorTests
- {
- private class TestStepExecutor : StepExecutor
- {
- readonly StringBuilder _builder = new();
-
- public string Results
- {
- get { return _builder.ToString(); }
- }
-
- public override object Execute(Step step, object testObject)
- {
- try
- {
- _builder.AppendLine(string.Format("About to run step '{0}'", step.Title));
- return base.Execute(step, testObject);
- }
- finally
- {
- _builder.AppendLine(string.Format("Finished running step '{0}'", step.Title));
- }
- }
- }
-
- [Fact]
- public void CustomizingStepExecutionByOverridingStepExecutor()
- {
- try
- {
- var testStepExecutor = new TestStepExecutor();
-
- Configurator.StepExecutor = testStepExecutor;
-
- new EmptyScenario()
- .Given(s => s.GivenSomething())
- .When(s => s.WhenSomething())
- .Then(s => s.ThenSomething())
- .BDDfy();
-
- string expected =
-@"About to run step 'Given something'
-Finished running step 'Given something'
-About to run step 'When something'
-Finished running step 'When something'
-About to run step 'Then something'
-Finished running step 'Then something'
-".Replace("\r", string.Empty).Trim();
-
- testStepExecutor.Results.Replace("\r", string.Empty).Trim().ShouldBe(expected);
- }
- finally
- {
- Configurator.StepExecutor = new StepExecutor();
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Configuration/TestRunnerTests.cs b/src/TestStack.BDDfy.Tests/Configuration/TestRunnerTests.cs
deleted file mode 100644
index f89aece7..00000000
--- a/src/TestStack.BDDfy.Tests/Configuration/TestRunnerTests.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-using System;
-using System.Linq;
-using Shouldly;
-using TestStack.BDDfy.Configuration;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Configuration
-{
- [Collection("ExclusiveAccessToConfigurator")]
- public class TestRunnerTests
- {
- public class ScenarioWithFailingThen
- {
- [Given]
- public void PassingGiven()
- {
- }
-
- [When]
- public void PassingWhen()
- {
- }
-
- [Then]
- public void FailingThen()
- {
- throw new Exception();
- }
-
- [AndThen]
- public void PassingAndThen()
- {
- }
- }
-
- public class When_StopExecutionOnFailingThen_IsSetToTrue
- {
- [Fact]
- public void FailingThenStopsThePipelineWithReflectiveAPI()
- {
- Configurator.Processors.TestRunner.StopExecutionOnFailingThen = true;
-
- try
- {
- var testRun = new ScenarioWithFailingThen().LazyBDDfy();
- Verify(testRun);
- }
- finally
- {
- Configurator.Processors.TestRunner.StopExecutionOnFailingThen = false;
- }
- }
-
- [Fact]
- public void FailingThenStopsThePipelineWithFluentAPI()
- {
- Configurator.Processors.TestRunner.StopExecutionOnFailingThen = true;
-
- try
- {
- var testRun = new ScenarioWithFailingThen()
- .Given(x => x.PassingGiven())
- .When(x => x.PassingWhen())
- .Then(x => x.FailingThen())
- .And(x => x.PassingAndThen())
- .LazyBDDfy();
-
- Verify(testRun);
- }
- finally
- {
- Configurator.Processors.TestRunner.StopExecutionOnFailingThen = false;
- }
- }
-
- private static void Verify(Engine testRun)
- {
- Should.Throw(() => testRun.Run());
- var scenario = testRun.Story.Scenarios.First();
- scenario.Result.ShouldBe(Result.Failed);
- var steps = scenario.Steps;
-
- steps.Count.ShouldBe(4);
- steps[0].Result.ShouldBe(Result.Passed);
- steps[0].ExecutionOrder.ShouldBe(ExecutionOrder.SetupState);
- steps[1].Result.ShouldBe(Result.Passed);
- steps[1].ExecutionOrder.ShouldBe(ExecutionOrder.Transition);
- steps[2].Result.ShouldBe(Result.Failed);
- steps[2].ExecutionOrder.ShouldBe(ExecutionOrder.Assertion);
- steps[3].Result.ShouldBe(Result.NotExecuted);
- steps[3].ExecutionOrder.ShouldBe(ExecutionOrder.ConsecutiveAssertion);
- }
- }
-
- public class When_StopExecutionOnFailingThen_IsLeftAsDefault
- {
- [Fact]
- public void FailingThenDoesNotStopThePipelineWithReflectiveAPI()
- {
- var testRun = new ScenarioWithFailingThen().LazyBDDfy();
- Verify(testRun);
- }
-
- [Fact]
- public void FailingThenDoesNotStopThePipelineWithFluentAPI()
- {
- Configurator.Processors.TestRunner.StopExecutionOnFailingThen = false;
-
- var testRun = new ScenarioWithFailingThen()
- .Given(x => x.PassingGiven())
- .When(x => x.PassingWhen())
- .Then(x => x.FailingThen())
- .And(x => x.PassingAndThen())
- .LazyBDDfy();
-
- Verify(testRun);
- }
-
- private static void Verify(Engine testRun)
- {
- Should.Throw(() => testRun.Run());
- var scenario = testRun.Story.Scenarios.First();
- scenario.Result.ShouldBe(Result.Failed);
- var steps = scenario.Steps;
-
- steps.Count.ShouldBe(4);
- steps[0].Result.ShouldBe(Result.Passed);
- steps[0].ExecutionOrder.ShouldBe(ExecutionOrder.SetupState);
- steps[1].Result.ShouldBe(Result.Passed);
- steps[1].ExecutionOrder.ShouldBe(ExecutionOrder.Transition);
- steps[2].Result.ShouldBe(Result.Failed);
- steps[2].ExecutionOrder.ShouldBe(ExecutionOrder.Assertion);
- steps[3].Result.ShouldBe(Result.Passed);
- steps[3].ExecutionOrder.ShouldBe(ExecutionOrder.ConsecutiveAssertion);
- }
- }
- }
-}
diff --git a/src/TestStack.BDDfy.Tests/DefaultHumanizerTests.cs b/src/TestStack.BDDfy.Tests/DefaultHumanizerTests.cs
deleted file mode 100644
index 7a5d7baf..00000000
--- a/src/TestStack.BDDfy.Tests/DefaultHumanizerTests.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-using System;
-using Shouldly;
-using TestStack.BDDfy.Configuration;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests
-{
- public class DefaultHumanizerTests
- {
- private static DefaultHumanizer Humanizer => new();
-
- [Fact]
- public void PascalCaseInputStringIsTurnedIntoSentence()
- {
- Humanizer.Humanize("PascalCaseInputStringIsTurnedIntoSentence")
- .ShouldBe("Pascal case input string is turned into sentence");
- }
-
- [Fact]
- public void WhenInputStringContainsConsequtiveCaptialLetters_ThenTheyAreTurnedIntoOneLetterWords()
- {
- Humanizer.Humanize("WhenIUseAnInputAHere").ShouldBe("When I use an input a here");
- }
-
- [Fact]
- public void WhenInputStringStartsWithANumber_ThenNumberIsDealtWithLikeAWord()
- {
- Humanizer.Humanize("10NumberIsInTheBegining").ShouldBe("10 number is in the begining");
- }
-
- [Fact]
- public void WhenInputStringEndWithANumber_ThenNumberIsDealtWithLikeAWord()
- {
- Humanizer.Humanize("NumberIsAtTheEnd100").ShouldBe("Number is at the end 100");
- }
-
- [Fact]
- public void UnderscoredInputStringIsTurnedIntoSentence()
- {
- Humanizer.Humanize("Underscored_input_string_is_turned_into_sentence")
- .ShouldBe("Underscored input string is turned into sentence");
- }
-
- [Fact]
- public void UnderscoredInputStringPreservesCasing()
- {
- Humanizer.Humanize("Underscored_input_String_is_turned_INTO_sentence")
- .ShouldBe("Underscored input String is turned INTO sentence");
- }
-
- [Fact]
- public void OneLetterWordInTheBeginningOfStringIsTurnedIntoAWord()
- {
- Humanizer.Humanize("XIsFirstPlayer").ShouldBe("X is first player");
- }
-
- [Theory]
- [InlineData("GivenThereAre__start__Cucumbers", "Given there are cucumbers")]
- [InlineData("Given_there_are__start__cucumbers", "Given there are cucumbers")]
- [InlineData("GivenThereAre__count1__Cucumbers", "Given there are cucumbers")]
- [InlineData("Given_there_are__count2__cucumbers", "Given there are cucumbers")] // The spacing rules for numbers are not consequential
- [InlineData("GivenMethodTaking__ExampleInt__", "Given method taking ")]
- [InlineData("Given_method_taking__ExampleInt__", "Given method taking ")]
- [InlineData("__starting__with_example", " with example")]
- [InlineData("__starting__WithExample", " with example")]
- [InlineData("WhenMethod__takes____two__parameters", "When method parameters")]
- [InlineData("When_method__takes____two__parameters", "When method parameters")]
- [InlineData("When_method_takes__one__and__two__parameters", "When method takes and parameters")]
- [InlineData("WhenMethodTakes__one__and__two__parameters", "When method takes and parameters")]
- public void CanDealWithExampleStepNames(string stepName, string expectedStepTitle)
- {
- Humanizer.Humanize(stepName).ShouldBe(expectedStepTitle);
- }
-
- [Theory]
- [InlineData("GivenThereAre__två__Cucumbers", "Given there are cucumbers")]
- public void ReportsIllegalExampleStepNames(string stepName, string expectedStepTitle) {
- var exception = Record.Exception(() => {
- Humanizer.Humanize(stepName).ShouldBe(expectedStepTitle);
- });
-
- exception.ShouldNotBeNull();
- exception.ShouldBeOfType();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Disposer/DisposingScenarios.cs b/src/TestStack.BDDfy.Tests/Disposer/DisposingScenarios.cs
deleted file mode 100644
index a47ad897..00000000
--- a/src/TestStack.BDDfy.Tests/Disposer/DisposingScenarios.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using System;
-using System.Linq;
-using Shouldly;
-using TestStack.BDDfy.Tests.Exceptions;
-using Xunit;
-using Xunit.Extensions;
-
-namespace TestStack.BDDfy.Tests.Disposer
-{
- public class DisposingScenarios
- {
- class DisposableScenario(ThrowingMethods throwingMethods): IDisposable
- {
- private readonly bool _givenThrows = (throwingMethods & ThrowingMethods.Given) > 0;
- private readonly bool _whenThrows = (throwingMethods & ThrowingMethods.When) > 0;
- private readonly bool _thenThrows = (throwingMethods & ThrowingMethods.Then) > 0;
-
- public void Given()
- {
- if (_givenThrows)
- throw new Exception();
- }
-
- public void When()
- {
- if (_whenThrows)
- throw new Exception();
- }
-
- public void Then()
- {
- if (_thenThrows)
- throw new Exception();
- }
-
- public void Dispose() { Disposed = true; }
-
- public bool Disposed { get; set; }
- }
-
- [Theory]
- [InlineData(ThrowingMethods.None)]
- [InlineData(ThrowingMethods.Given)]
- [InlineData(ThrowingMethods.When)]
- [InlineData(ThrowingMethods.Then)]
- [InlineData(ThrowingMethods.Given | ThrowingMethods.When | ThrowingMethods.Then)]
- public void Execute(ThrowingMethods throwingMethods)
- {
- var scenario = new DisposableScenario(throwingMethods);
-
- var bddifier = scenario.LazyBDDfy();
- try
- {
- // we need TestObject for this test; so I disable StoryCache processor for this one test
- BDDfy.Configuration.Configurator.Processors.StoryCache.Disable();
- bddifier.Run();
- }
- catch (Exception)
- {
- // there will be an exception but we do not care about it
- }
- finally
- {
- BDDfy.Configuration.Configurator.Processors.StoryCache.Enable();
- }
- var story = bddifier.Story;
-
- story.Scenarios.All(s => ((DisposableScenario)s.TestObject).Disposed).ShouldBe(false);
- scenario.Disposed.ShouldBe(false);
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/ExceptionThrowingTest.cs b/src/TestStack.BDDfy.Tests/Exceptions/ExceptionThrowingTest.cs
deleted file mode 100644
index 1ca455cd..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/ExceptionThrowingTest.cs
+++ /dev/null
@@ -1,165 +0,0 @@
-using System;
-using System.Linq;
-using Shouldly;
-
-namespace TestStack.BDDfy.Tests.Exceptions
-{
- public class ExceptionThrowingTest where T : Exception, new()
- {
- private bool _givenShouldThrow;
- private bool _whenShouldThrow;
- private bool _thenShouldThrow;
- Scenario _scenario;
-
- void Given()
- {
- if (_givenShouldThrow)
- throw new T();
- }
-
- void When()
- {
- if(_whenShouldThrow)
- throw new T();
- }
-
- void Then()
- {
- if (_thenShouldThrow)
- throw new T();
- }
-
- void TearDown()
- {
- }
-
- public void Execute(ThrowingMethods methodToThrow, bool useFluentScanner)
- {
- SetThrowingStep(methodToThrow);
-
- Engine engine = useFluentScanner ? FluentScannerBddifier() : ReflectingScannersBddifier();
-
- try
- {
- engine.Run();
- }
- finally
- {
- Story = engine.Story;
- _scenario = engine.Story.Scenarios.First();
- }
- }
-
- private Engine FluentScannerBddifier()
- {
- return this.Given(s => s.Given())
- .When(s => s.When())
- .Then(s => s.Then())
- .TearDownWith(s => s.TearDown())
- .LazyBDDfy();
- }
-
- private Engine ReflectingScannersBddifier()
- {
- return this.LazyBDDfy();
- }
-
- private void SetThrowingStep(ThrowingMethods methodToThrow)
- {
- _givenShouldThrow = false;
- _whenShouldThrow = false;
- _thenShouldThrow = false;
-
- switch (methodToThrow)
- {
- case ThrowingMethods.Given:
- _givenShouldThrow = true;
- break;
-
- case ThrowingMethods.When:
- _whenShouldThrow = true;
- break;
-
- case ThrowingMethods.Then:
- _thenShouldThrow = true;
- break;
- }
- }
-
- private Step GetStep(string stepTitle)
- {
- return _scenario.Steps.First(s => s.Title == stepTitle);
- }
-
- Step GivenStep
- {
- get
- {
- return GetStep("Given");
- }
- }
-
- Step WhenStep
- {
- get {
- return GetStep("When");
- }
- }
-
- Step ThenStep
- {
- get
- {
- return GetStep("Then");
- }
- }
-
- Step TearDownStep
- {
- get
- {
- return GetStep("Tear down");
- }
- }
-
- Scenario Scenario
- {
- get
- {
- return _scenario;
- }
- }
-
- Story Story { get; set; }
-
- public void AssertTearDownMethodIsExecuted()
- {
- TearDownStep.Result.ShouldBe(Result.Passed);
- }
-
- public void AssertGivenStepResult(Result result)
- {
- GivenStep.Result.ShouldBe(result);
- }
-
- public void AssertWhenStepResult(Result result)
- {
- WhenStep.Result.ShouldBe(result);
- }
-
- public void AssertThenStepResult(Result result)
- {
- ThenStep.Result.ShouldBe(result);
- }
-
- public void AssertScenarioResult(Result result)
- {
- Scenario.Result.ShouldBe(result);
- }
-
- public void AssertStoryResult(Result result)
- {
- Story.Result.ShouldBe(result);
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/ExceptionsWhenUsingExamples.cs b/src/TestStack.BDDfy.Tests/Exceptions/ExceptionsWhenUsingExamples.cs
deleted file mode 100644
index 5bc1fb53..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/ExceptionsWhenUsingExamples.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Exceptions
-{
- public class ExceptionsWhenUsingExamples
- {
- [Fact]
- public void CorrectlyReportsErrorWhenAllStepsNotRun()
- {
- Should.Throw(() =>
- {
- var exampleTable = new ExampleTable("Arg1", "Arg2")
- {
- {"foo", "bar"},
- {"foo", "bar"}
- };
-
- string arg1 = null;
- string arg2 = null;
- var arg3 = default(string);
- this.Given(_ => AFailingStep(arg1), "Given a failing step")
- .Then(_ => NonExecutedStep(arg2), "Then multiple assertions")
- .And(_ => NonExecutedStep(arg3), "The second one blows up")
- .WithExamples(exampleTable)
- .BDDfy();
- });
- }
-
- private void NonExecutedStep(string s)
- {
-
- }
-
- private void AFailingStep(string s)
- {
- throw new InvalidOperationException();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/NotImplementedExceptionBase.cs b/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/NotImplementedExceptionBase.cs
deleted file mode 100644
index 4bd38337..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/NotImplementedExceptionBase.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace TestStack.BDDfy.Tests.Exceptions.NotImplementedException
-{
- public class NotImplementedExceptionBase
- {
- protected readonly ExceptionThrowingTest Sut;
-
- public NotImplementedExceptionBase()
- {
- Sut = new ExceptionThrowingTest();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenGivenThrowsNotImplementedException.cs b/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenGivenThrowsNotImplementedException.cs
deleted file mode 100644
index 27240924..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenGivenThrowsNotImplementedException.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-using System;
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Exceptions.NotImplementedException
-{
- public class WhenGivenThrowsNotImplementedException : NotImplementedExceptionBase
- {
- private void ExecuteUsingFluentScanner()
- {
- var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.Given, true));
- ex.GetType().FullName.ShouldContain("Inconclusive");
- }
-
- private void ExecuteUsingReflectingScanners()
- {
- var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.Given, false));
- ex.GetType().FullName.ShouldContain("Inconclusive");
- }
-
- [Fact]
- public void GivenIsReportedAsNotImplementedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertGivenStepResult(Result.NotImplemented);
- }
-
- [Fact]
- public void GivenIsReportedAsNotImplementedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertGivenStepResult(Result.NotImplemented);
- }
-
- [Fact]
- public void WhenIsNotExecutedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertWhenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void WhenIsNotExecutedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertWhenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void ThenIsNotExecutedWhenUsingReflectingScanner()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertThenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void ThenIsNotExecutedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertThenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void ScenarioResultReturnsNotImplementedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertScenarioResult(Result.NotImplemented);
- }
-
- [Fact]
- public void ScenarioResultReturnsNotImplementedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertScenarioResult(Result.NotImplemented);
- }
-
- [Fact]
- public void StoryResultReturnsNotImplementedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertStoryResult(Result.NotImplemented);
- }
-
- [Fact]
- public void StoryResultReturnsNotImplementedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertStoryResult(Result.NotImplemented);
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertTearDownMethodIsExecuted();
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertTearDownMethodIsExecuted();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenThenThrowsNotImplementedException.cs b/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenThenThrowsNotImplementedException.cs
deleted file mode 100644
index 1f00d20e..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenThenThrowsNotImplementedException.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-using System;
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Exceptions.NotImplementedException
-{
- public class WhenThenThrowsNotImplementedException : NotImplementedExceptionBase
- {
- private void ExecuteUsingReflectingScanners()
- {
- var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.Then, false));
- ex.GetType().FullName.ShouldContain("Inconclusive");
- }
-
- private void ExecuteUsingFluentScanner()
- {
- var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.Then, true));
- ex.GetType().FullName.ShouldContain("Inconclusive");
- }
-
- [Fact]
- public void GivenIsReportedAsSuccessfulWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertGivenStepResult(Result.Passed);
- }
-
- [Fact]
- public void WhenIsReportedAsSuccessfulWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertWhenStepResult(Result.Passed);
- }
-
- [Fact]
- public void ThenIsReportedAsNotImplemenetedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertThenStepResult(Result.NotImplemented);
- }
-
- [Fact]
- public void ScenarioResultReturnsNoImplementedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertScenarioResult(Result.NotImplemented);
- }
-
- [Fact]
- public void StoryResultReturnsNoImplementedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertStoryResult(Result.NotImplemented);
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertTearDownMethodIsExecuted();
- }
-
- [Fact]
- public void GivenIsReportedAsSuccessfulWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertGivenStepResult(Result.Passed);
- }
-
- [Fact]
- public void WhenIsReportedAsSuccessfulWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertWhenStepResult(Result.Passed);
- }
-
- [Fact]
- public void ThenIsReportedAsNotImplemenetedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertThenStepResult(Result.NotImplemented);
- }
-
- [Fact]
- public void ScenarioResultReturnsNoImplementedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertScenarioResult(Result.NotImplemented);
- }
-
- [Fact]
- public void StoryResultReturnsNoImplementedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertStoryResult(Result.NotImplemented);
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertTearDownMethodIsExecuted();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenWhenThrowsNotImplementedException.cs b/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenWhenThrowsNotImplementedException.cs
deleted file mode 100644
index 1788f865..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenWhenThrowsNotImplementedException.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-using System;
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Exceptions.NotImplementedException
-{
- public class WhenWhenThrowsNotImplementedException : NotImplementedExceptionBase
- {
- private void ExecuteUsingReflectingScanners()
- {
- var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.When, false));
- ex.GetType().FullName.ShouldContain("Inconclusive");
- }
-
- private void ExecuteUsingFluentScanner()
- {
- var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.When, true));
- ex.GetType().FullName.ShouldContain("Inconclusive");
- }
-
- [Fact]
- public void GivenIsReportedAsSuccessfulWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertGivenStepResult(Result.Passed);
- }
-
- [Fact]
- public void WhenIsReportedAsNotImplementedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertWhenStepResult(Result.NotImplemented);
- }
-
- [Fact]
- public void ThenIsNotExecutedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertThenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void ScenarioResultReturnsNotImplementedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertScenarioResult(Result.NotImplemented);
- }
-
- [Fact]
- public void StoryResultReturnsNotImplementedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertStoryResult(Result.NotImplemented);
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertTearDownMethodIsExecuted();
- }
-
- [Fact]
- public void GivenIsReportedAsSuccessfulWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertGivenStepResult(Result.Passed);
- }
-
- [Fact]
- public void WhenIsReportedAsNotImplementedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertWhenStepResult(Result.NotImplemented);
- }
-
- [Fact]
- public void ThenIsNotExecutedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertThenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void ScenarioResultReturnsNotImplementedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertScenarioResult(Result.NotImplemented);
- }
-
- [Fact]
- public void StoryResultReturnsNotImplementedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertStoryResult(Result.NotImplemented);
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertTearDownMethodIsExecuted();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/OtherExceptionBase.cs b/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/OtherExceptionBase.cs
deleted file mode 100644
index ffc4a4c1..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/OtherExceptionBase.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-
-namespace TestStack.BDDfy.Tests.Exceptions.OtherExceptions
-{
- public class OtherExceptionBase
- {
- protected readonly ExceptionThrowingTest Sut;
-
- public OtherExceptionBase()
- {
- Sut = new ExceptionThrowingTest();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenGivenThrowsException.cs b/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenGivenThrowsException.cs
deleted file mode 100644
index e34a5203..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenGivenThrowsException.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-using System;
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Exceptions.OtherExceptions
-{
- public class WhenGivenThrowsException : OtherExceptionBase
- {
- private void ExecuteUsingReflectingScanners()
- {
- Should.Throw(() => Sut.Execute(ThrowingMethods.Given, false));
- }
-
- private void ExecuteUsingFluentScanners()
- {
- Should.Throw(() => Sut.Execute(ThrowingMethods.Given, true));
- }
-
- [Fact]
- public void GivenShouldBeReportedAsFailedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertGivenStepResult(Result.Failed);
- }
-
- [Fact]
- public void WhenShouldNotBeExecutedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertWhenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void ThenShouldNotBeExecutedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertThenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void ScenarioResultReturnsFailedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertScenarioResult(Result.Failed);
- }
-
- [Fact]
- public void StoryResultReturnsFailedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertStoryResult(Result.Failed);
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertTearDownMethodIsExecuted();
- }
-
- [Fact]
- public void GivenShouldBeReportedAsFailedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanners();
- Sut.AssertGivenStepResult(Result.Failed);
- }
-
- [Fact]
- public void WhenShouldNotBeExecutedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanners();
- Sut.AssertWhenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void ThenShouldNotBeExecutedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanners();
- Sut.AssertThenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void ScenarioResultReturnsFailedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanners();
- Sut.AssertScenarioResult(Result.Failed);
- }
-
- [Fact]
- public void StoryResultReturnsFailedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanners();
- Sut.AssertStoryResult(Result.Failed);
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanners();
- Sut.AssertTearDownMethodIsExecuted();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenResolvingExceptionsFromDifferentScanners.cs b/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenResolvingExceptionsFromDifferentScanners.cs
deleted file mode 100644
index 7c59bdc8..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenResolvingExceptionsFromDifferentScanners.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using System;
-using System.Xml;
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Exceptions.OtherExceptions
-{
- public class WhenResolvingExceptionsFromDifferentScanners
- {
- private ExceptionThrowingTest _sut;
-
- ///
- /// Test to resolve issue where fluent scanner was returning the inner exception rather than the outer one.
- /// Issue 17: https://github.com/TestStack/TestStack.BDDfy/issues/17
- ///
- [Fact]
- public void FluentScannerShouldReturnOriginalExceptionAndNotInnerException()
- {
- _sut = new ExceptionThrowingTest();
- Should.Throw(() => _sut.Execute(ThrowingMethods.Given, true));
- }
-
- [Fact]
- public void ReflectiveScannerShouldReturnOriginalExceptionAndNotTargetInvocationException()
- {
- _sut = new ExceptionThrowingTest();
- Should.Throw(() => _sut.Execute(ThrowingMethods.Given, false));
- }
-
- private class OuterException : Exception
- {
- public OuterException()
- : base("outer", new XmlException("inner exception"))
- {
- }
- }
- }
-}
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenThenThrowsException.cs b/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenThenThrowsException.cs
deleted file mode 100644
index c1eab33d..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenThenThrowsException.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-using System;
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Exceptions.OtherExceptions
-{
- public class WhenThenThrowsException : OtherExceptionBase
- {
- private void ExecuteUsingReflectingScanners()
- {
- Should.Throw(() => Sut.Execute(ThrowingMethods.Then, false));
- }
-
- private void ExecuteUsingFluentScanner()
- {
- Should.Throw(() => Sut.Execute(ThrowingMethods.Then, true));
- }
-
- [Fact]
- public void GivenIsReportedAsSuccessfulWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertGivenStepResult(Result.Passed);
- }
-
- [Fact]
- public void WhenIsReportedAsSuccessfulWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertWhenStepResult(Result.Passed);
- }
-
- [Fact]
- public void ThenIsReportedAsFailedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertThenStepResult(Result.Failed);
- }
-
- [Fact]
- public void ScenarioResultReturnsFailedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertScenarioResult(Result.Failed);
- }
-
- [Fact]
- public void StoryResultReturnsFailedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertStoryResult(Result.Failed);
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertTearDownMethodIsExecuted();
- }
-
- [Fact]
- public void GivenIsReportedAsSuccessfulWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertGivenStepResult(Result.Passed);
- }
-
- [Fact]
- public void WhenIsReportedAsSuccessfulWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertWhenStepResult(Result.Passed);
- }
-
- [Fact]
- public void ThenIsReportedAsFailedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertThenStepResult(Result.Failed);
- }
-
- [Fact]
- public void ScenarioResultReturnsFailedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertScenarioResult(Result.Failed);
- }
-
- [Fact]
- public void StoryResultReturnsFailedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertStoryResult(Result.Failed);
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingFluentScanners()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertTearDownMethodIsExecuted();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenWhenThrowsException.cs b/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenWhenThrowsException.cs
deleted file mode 100644
index 11741e33..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenWhenThrowsException.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-using System;
-using Shouldly;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Exceptions.OtherExceptions
-{
- public class WhenWhenThrowsException : OtherExceptionBase
- {
- private void ExecuteUsingFluentScanner()
- {
- Should.Throw(() => Sut.Execute(ThrowingMethods.When, true));
- }
-
- private void ExecuteUsingReflectingScanners()
- {
- Should.Throw(() => Sut.Execute(ThrowingMethods.When, false));
- }
-
- [Fact]
- public void GivenIsReportedAsSuccessfulWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertGivenStepResult(Result.Passed);
- }
-
- [Fact]
- public void GivenIsReportedAsSuccessfulWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertGivenStepResult(Result.Passed);
- }
-
- [Fact]
- public void WhenIsReportedAsFailedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertWhenStepResult(Result.Failed);
- }
-
- [Fact]
- public void WhenIsReportedAsFailedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertWhenStepResult(Result.Failed);
- }
-
- [Fact]
- public void ThenIsNotExecutedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertThenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void ThenIsNotExecutedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertThenStepResult(Result.NotExecuted);
- }
-
- [Fact]
- public void ScenarioResultReturnsFailedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertScenarioResult(Result.Failed);
- }
-
- [Fact]
- public void ScenarioResultReturnsFailedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertScenarioResult(Result.Failed);
- }
-
- [Fact]
- public void StoryResultReturnsFailedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertStoryResult(Result.Failed);
- }
-
- [Fact]
- public void StoryResultReturnsFailedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertStoryResult(Result.Failed);
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingReflectingScanners()
- {
- ExecuteUsingReflectingScanners();
- Sut.AssertTearDownMethodIsExecuted();
- }
-
- [Fact]
- public void TearDownMethodIsExecutedWhenUsingFluentScanner()
- {
- ExecuteUsingFluentScanner();
- Sut.AssertTearDownMethodIsExecuted();
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/ThrowingMethods.cs b/src/TestStack.BDDfy.Tests/Exceptions/ThrowingMethods.cs
deleted file mode 100644
index 5a09e2f7..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/ThrowingMethods.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-
-namespace TestStack.BDDfy.Tests.Exceptions
-{
- [Flags]
- public enum ThrowingMethods
- {
- None = 0,
- Given = 1,
- When = 2,
- Then = 4
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Exceptions/WhenAnInconclusiveTestIsRun.cs b/src/TestStack.BDDfy.Tests/Exceptions/WhenAnInconclusiveTestIsRun.cs
deleted file mode 100644
index 67a2e548..00000000
--- a/src/TestStack.BDDfy.Tests/Exceptions/WhenAnInconclusiveTestIsRun.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-using System.Linq;
-using Shouldly;
-using TestStack.BDDfy.Processors;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Exceptions
-{
- public class WhenAnInconclusiveTestIsRun
- {
- public class InconclusiveTestClass
- {
- public void GivenAClassUnderTest()
- {
- }
-
- public void WhenInconclusiveExceptionIsThrownInOneOfTheMethods()
- {
- }
-
- public void ThenTheContextIsFlaggedAsInconclusive()
- {
- throw new InconclusiveException();
- }
-
- public void TearDownThis()
- {
-
- }
- }
-
- Engine _engine;
- private Scenario _scenario;
-
- Step GivenStep
- {
- get
- {
- return _scenario.Steps.Single(s => s.Title == "Given a class under test");
- }
- }
-
- Step WhenStep
- {
- get
- {
- return _scenario.Steps.Single(s => s.Title == "When inconclusive exception is thrown in one of the methods");
- }
- }
-
- Step ThenStep
- {
- get
- {
- return _scenario.Steps.Single(s => s.Title == "Then the context is flagged as inconclusive");
- }
- }
-
- Step DisposeStep
- {
- get
- {
- return _scenario.Steps.Single(s => s.Title == "Tear down this");
- }
- }
-
- public WhenAnInconclusiveTestIsRun()
- {
- _engine = new InconclusiveTestClass().LazyBDDfy();
- Should.Throw(() => _engine.Run());
- _scenario = _engine.Story.Scenarios.First();
- }
-
- [Fact]
- public void ResultIsInconclusive()
- {
- _scenario.Result.ShouldBe(Result.Inconclusive);
- }
-
- [Fact]
- public void ThenIsFlaggedAsInconclusive()
- {
- ThenStep.Result.ShouldBe(Result.Inconclusive);
- }
-
- [Fact]
- public void ThenHasAnInconclusiveExceptionOnIt()
- {
- ThenStep.Exception.ShouldBeAssignableTo();
- }
-
- [Fact]
- public void GivenIsFlaggedAsSuccessful()
- {
- GivenStep.Result.ShouldBe(Result.Passed);
- }
-
- [Fact]
- public void WhenIsFlaggedAsSuccessful()
- {
- WhenStep.Result.ShouldBe(Result.Passed);
- }
-
- [Fact]
- public void ScenarioResultReturnsInconclusive()
- {
- _scenario.Result.ShouldBe(Result.Inconclusive);
- }
-
- [Fact]
- public void StoryResultReturnsInconclusive()
- {
- _scenario.Result.ShouldBe(Result.Inconclusive);
- }
-
- [Fact]
- public void TearDownMethodIsExecuted()
- {
- DisposeStep.Result.ShouldBe(Result.Passed);
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/ExclusiveAccessToConfiguratorFixture.cs b/src/TestStack.BDDfy.Tests/ExclusiveAccessToConfiguratorFixture.cs
deleted file mode 100644
index 2c9f5f33..00000000
--- a/src/TestStack.BDDfy.Tests/ExclusiveAccessToConfiguratorFixture.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Xunit;
-
-namespace TestStack.BDDfy.Tests
-{
- [CollectionDefinition("ExclusiveAccessToConfigurator", DisableParallelization = true)]
- public class ExclusiveAccessToConfiguratorFixture
- {
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Helpers.cs b/src/TestStack.BDDfy.Tests/Helpers.cs
deleted file mode 100644
index 162bde49..00000000
--- a/src/TestStack.BDDfy.Tests/Helpers.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-using System.Linq.Expressions;
-using System.Reflection;
-
-namespace TestStack.BDDfy.Tests
-{
- public class Helpers
- {
- public static MethodInfo GetMethodInfo(Expression methodOn)
- {
- var methodCallExp = (MethodCallExpression)methodOn.Body;
- return methodCallExp.Method;
- }
- }
-}
\ No newline at end of file
diff --git a/src/TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs b/src/TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs
deleted file mode 100644
index 85b32b7f..00000000
--- a/src/TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Shouldly;
-using TestStack.BDDfy.Processors;
-using Xunit;
-
-namespace TestStack.BDDfy.Tests.Processors
-{
- public class TestRunnerTests
- {
- public int ExampleValue { get; set; }
-
- [Fact]
- public void InitializesScenarioWithExampleBeforeRunning()
- {
- const int expectedValue = 1;
- var actualValue = 0;
- var exampleTable = new ExampleTable("ExampleValue")
- {
- expectedValue
- }.Single();
-
- var sut = new TestRunner();
- Func