Simple-Bdd 1.0.0

dotnet add package Simple-Bdd --version 1.0.0
NuGet\Install-Package Simple-Bdd -Version 1.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Simple-Bdd" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Simple-Bdd --version 1.0.0
#r "nuget: Simple-Bdd, 1.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Simple-Bdd as a Cake Addin
#addin nuget:?package=Simple-Bdd&version=1.0.0

// Install Simple-Bdd as a Cake Tool
#tool nuget:?package=Simple-Bdd&version=1.0.0

Cucumber-like bdd tests

Simple cucumber-like test framework to use on Universal Windows App platform or any other project because of .net standard 1.1 as target

The goal of this project is to create some simple BDD framework. The reasons:

  1. The SpecFlow team isn't going to support UWP. At least now. They might in future but I need something for now. I didn't find anything usable
  2. Try and learn some features and .net standard project
  3. Just for fun

Unfortunately Microsoft Universal Windows Platform has poor support of unit testing at all. There are some restrictions. So as result this solution is also going to have restrictions. But in any case I'll try to do it in the handiest and usable way.

In this solution I'm goint to use Gerkins-like syntax. If you don't know what it means then google it 😃

Examples of usage

Can be found here

[TestClass]
public class ScenarioRunTests : BaseTestClass
{
    [TestMethod]
    public void ScenarioRunsTestWithAllStatementsWithoutExceptions()
    {
        new Scenario(typeof(ScenarioRunTests))
            .Given("Given test method puts into context 10 for key 'GivenKey'")
                .And("And given test method puts into context 'and' for key 'GivenAsAndKey'")
                .And("And given test method puts table value from column 'Value' into context with 'TableKey' key",
                    new Table(
                        new [] { "Value" },
                        new []
                            {
                                new object[] { 1.1 }
                            }
                        )
                    )
            .When("When test method joins 'GivenKey' and 'GivenAsAndKey' values as string to 'WhenResultKey' as result")
                .And("And when test method concats 'TableKey' value to 'WhenResultKey'")
            .Then("Value with key 'WhenResultKey' in the result context is a string")
                .And("Value with key 'WhenResultKey' in the result context should be equal '10and1.1'")
            .Run();
    }

    [Given(@"Given test method puts into context (\d+) for key '(.+)'")]
    [Given(@"And given test method puts into context '(.+)' for key '(.+)'")]
    private static void GivenTestMethodPutsIntoContextValueForKey(object value, string key)
    {
        Put(value, key);
    }

    [Given(@"And given test method puts table value from column '(.+)' into context with '(.+)' key")]

    private static void GivenAndTestMethodPutsTableValueFromColumnIntoContextWithKey(Table table,
        string columnName, string key)
    {
        Put(table.Rows.First().GetValue<double>(columnName), key);
    }

    [When(@"When test method joins '(.+)' and '(.+)' values as string to '(.+)' as result")]
    private static void WhenTestMethodPutsIntoContextValueForKey(string firstKey, string secondKey,
        string resultKey)
    {
        PutResult($"{Get<object>(firstKey)}{Get<object>(secondKey)}", resultKey);
    }

    [When(@"And when test method concats '(.+)' value to '(.+)'")]
    private static void WhenAndTestMethodConcatsValueFromKeyToResultValueFromKey(string key, string resultKey)
    {
        PutResult($"{GetResult<object>(resultKey)}{Get<object>(key)}", resultKey);
    }

    [Then("Value with key '(.+)' in the result context is a string")]
    private static void ThenValueWithKeyInTheResultContextIsAString(string resultKey)
    {
        (GetResult<object>(resultKey) is string).Should().BeTrue();
    }

    [Then("Value with key '(.+)' in the result context should be equal '(.+)'")]
    private static void ThenValueWithKeyInTheResultContextIsAString(string resultKey, string expectedValue)
    {
        GetResult<string>(resultKey).Should().Be(expectedValue);
    }
}
[TestClass]
public class ScenarioRunTests
{
    [TestMethod]
    public void ScenarioAwaitesAwaitableMethodsForAllStatements()
    {
        new Scenario(typeof(ScenarioRunTests))
            .Given("Awaitable method post time to 'Given' key and time to 'GivenAfterNSeconds' key after 3 seconds")
            .When("Awaitable method post time to 'When' key and time to 'WhenAfterNSeconds' key after 3 seconds")
            .Then("Awaitable method post time to 'Then' key and time to 'ThenAfterNSeconds' key after 3 seconds")
                .And("Time in 'GivenAfterNSeconds' is greater or equals to time in 'Given' by 3 seconds")
                .And("Time in 'WhenAfterNSeconds' is greater or equals to time in 'When' by 3 seconds")
                .And("Time in 'ThenAfterNSeconds' is greater or equals to time in 'Then' by 3 seconds")
            .Run();
    }

    [Given("Awaitable method post time to '(.+)' key and time to '(.+)' key after (.+) seconds")]
    [Then("Awaitable method post time to '(.+)' key and time to '(.+)' key after (.+) seconds")]
    private static async Task GivenAwaitableMethodPostTimeToKeyAndTimeToKeyAfterSeconds(ScenarioContext context,
        string key, string secondKey, int secondToWait)
    {
        context.PutResult(DateTime.UtcNow, key);
        await Task.Delay(TimeSpan.FromSeconds(secondToWait));
        context.PutResult(DateTime.UtcNow, secondKey);
    }

    [When("Awaitable method post time to '(.+)' key and time to '(.+)' key after (.+) seconds")]
    private static async Task<int> WhenAwaitableMethodPostTimeToKeyAndTimeToKeyAfterSeconds(
        ScenarioContext context, string key, string secondKey, int secondToWait)
    {
        context.PutResult(DateTime.UtcNow, key);
        await Task.Delay(TimeSpan.FromSeconds(secondToWait));
        context.PutResult(DateTime.UtcNow, secondKey);
        return 1;
    }

    [Then("Time in '(.+)' is greater or equals to time in '(.+)' by (.+) seconds")]
    private static void TimeInIsGreaterOrEqualsToTimeInBySeconds(ScenarioContext context, string secondKey,
        string key, int expectedDifferenceInSeconds)
    {
        DateTime secondTime = context.GetResult<DateTime>(secondKey);
        DateTime firstTime = context.GetResult<DateTime>(key);

        TimeSpan difference = secondTime - firstTime;

        difference.TotalSeconds.Should().BeGreaterOrEqualTo(expectedDifferenceInSeconds);
    }
}

ScenarioContext class restrictions

ScenarioContext.Current is thread safe but it is shared between scenarios. So it is quite possible that when you create some sequential tests you can override values or see unexpected values in current context. So please clear context before running scenario if you use ScenarioContext.Current and see some strange behavior.

As alternative you can declare ScenarioContext parameter in your test method and ScenarioContext will be passed to you method. At this time ScenarioContext is shared only between methods of your scenario.

Tool to convert scenarios to methods

There is a simple tool to convert scenarios to test methods. Clone solution, build and check.

Check on github alternative way of using

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp1.0 was computed.  netcoreapp1.1 was computed.  netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard1.1 is compatible.  netstandard1.2 was computed.  netstandard1.3 was computed.  netstandard1.4 was computed.  netstandard1.5 was computed.  netstandard1.6 was computed.  netstandard2.0 was computed.  netstandard2.1 was computed. 
.NET Framework net45 was computed.  net451 was computed.  net452 was computed.  net46 was computed.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen30 was computed.  tizen40 was computed.  tizen60 was computed. 
Universal Windows Platform uap was computed.  uap10.0 was computed. 
Windows Phone wpa81 was computed. 
Windows Store netcore was computed.  netcore45 was computed.  netcore451 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0 1,034 10/12/2017