Migrating LightBDD Versions

Wojtek edited this page Sep 1, 2018 · 21 revisions

Migrating LightBDD 1.x to 2.x

This page describes how to migrate from LightBDD 1.x to 2.x series. To see example tests projects written in LightBDD 2.x, please browse the examples directory in the repository.

Migration process in a nutshell

  • Update all the existing packages to version 2.X
    • Ensure that there is no LightBDD packages of version 1.X left in the project
    • For pre 2017 version of csproj/packages.config format, ensure that LightBDD.Core and LightBDD.Framework packages are present
    • If upgrading from LightBDD.NUnit, ensure that LightBDD.NUnit2 is present (LightBDD.NUnit package can be removed after upgrade)
    • If upgrading from LightBDD.XUnit, ensure that LightBDD.XUnit2 is present (LightBDD.XUnit package can be removed after upgrade)
    • If LightBDD.MsTest package is used, please uninstall it, and install LightBDD.MsTest2 (that uses MsTest.Framework package)
    • The LightBDD.MbUnit is no longer supported
  • Add using LightBDD.NUnit2 / LightBDD.NUnit3 / LightBDD.XUnit2 / LightBDD.MsTest2 in test classes in order to recognize FeatureFixture and [Scenario] attribute
  • Add using LightBDD.Framework in test classes in order to recognize [Label], [FeatureDescription] and [ScenarioCategory]
  • Change all scenario test method attributes from [Test]/[TestMethod]/[Fact]/[Theory] to [Scenario]
  • Update namespaces to properly recognize Runner.RunScenario*() extension methods:
    • using LightBDD.Framework.Scenarios.Basic for basic syntax
    • using LightBDD.Framework.Scenarios.Extended for extended syntax
    • using LightBDD.Framework.Scenarios.Contextual for scenarios with context
  • Add LightBDD scope to the project:
    • For NUnit2 / NUnit3 / XUnit2, add [assembly: LightBddScope]
    • For MsTest2 add
      [TestClass]
      public class LightBddIntegration
      {
          [AssemblyInitialize]
          public static void Setup(TestContext testContext) { LightBddScope.Initialize(); }
          [AssemblyCleanup]
          public static void Cleanup() { LightBddScope.Cleanup(); }
      }
    • For all test frameworks, remove [assembly: Debuggable(true, true)] if present
  • If app.config has some LightBDD configuration, please read Migrating configuration how to migrate it.

Example NUnit3 LightBDD feature class using basic scenario syntax:

using LightBDD.Framework;
using LightBDD.Framework.Scenarios.Basic;
using LightBDD.NUnit3;

namespace Example.LightBDD.NUnit3.Features
{
    [FeatureDescription(
@"In order to access personal data
As an user
I want to login into system")]
    [Label("Story-1")]
    public partial class Login_feature
    {
        [Scenario]
        [Label("Ticket-1")]
        [ScenarioCategory(Categories.Security)]
        public void Successful_login()
        {
            Runner.RunScenario(

                Given_the_user_is_about_to_login,
                Given_the_user_entered_valid_login,
                Given_the_user_entered_valid_password,
                When_the_user_clicks_login_button,
                Then_the_login_operation_should_be_successful,
                Then_a_welcome_message_containing_user_name_should_be_returned);
        }
        /* ... */
    }
}

and the implementation side:

using LightBDD.Framework;
using LightBDD.Framework.Commenting;
using LightBDD.NUnit3;
using NUnit.Framework;

namespace Example.LightBDD.NUnit3.Features
{
    public partial class Login_feature : FeatureFixture
    {
        private void Given_the_user_entered_anonymous_login()
        {
            StepExecution.Current.Comment("Presentation of failed scenario");
            /* ... */
        }
        /* ... */
    }
}

The steps above should allow to migrate most of the projects. In some scenarios it may be necessary however to make some more amendments - for those cases, please read the rest of the document.

Updating packages

The following table describes package changes between LightBDD versions with details how to update:

Package Description LightBDD 1.x LightBDD 2.x Update notes
LightBDD.NUnit3 LightBDD integration with NUnit 3 1.7.3 2.0.0 nuget update
LightBDD.NUnit2 LightBDD integration with NUnit 2 n/a 2.1.0 renamed from LightBDD.NUnit
LightBDD.NUnit LightBDD integration with NUnit 2 1.7.3 2.1.0 version 2.1.0 adds dependency on LightBDD.NUnit2 which is the successor (deprecated)
LightBDD.MsTest LightBDD integration with MsTest 1.7.3 deprecated The package is deprecated. LightBDD.MsTest2 should be used instead.
LightBDD.MsTest2 LightBDD integration with MsTest2 n/a 2.0.0 a new integration
LightBDD.XUnit LightBDD integration with XUnit 2 1.7.3 2.1.0 version 2.1.0 adds dependency on LightBDD.XUnit2 which is the successor (deprecated)
LightBDD.XUnit2 LightBDD integration with XUnit 2 1.7.3 2.0.0 nuget update
LightBDD.MbUnit LightBDD integration with MbUnit 1.7.3 deprecated MbUnit is no longer supported
LightBDD.Core Core implementation of LightBDD mechanisms 1.7.3 2.0.0 nuget update
LightBDD.Framework LightBDD framework containing LightBDD features n/a 2.0.0 a new package, automatically included by integration packages
LightBDD Meta-package referencing to LightBDD.NUnit 1.7.3 2.1.0 version 2.1.0 adds dependency on LightBDD.NUnit2 to simplify update, but will no longer be maintained (deprecated)

Updating namespaces

With LightBDD 2.x the LightBDD.Framework package has been introduced and namespaces have been unified in all projects to reflect the assembly where classes belongs to as well as to separate LightBDD features. Below, there is a list of namespaces with corresponding features used to describe and execute tests:

  • LightBDD.Framework
    • IBddRunner,IBddRunner<TContext>
    • FeatureDescriptionAttribute
    • LabelAttribute
    • ScenarioCategoryAttribute
    • StepExecution
  • LightBDD.Framework.Commenting
    • StepExecutionExtensions allowing to call StepExecution.Current.Comment(...)
  • LightBDD.Framework.Formatting
    • FormatAttribute
    • FormatBooleanAttribute
    • FormatCollectionAttribute
  • LightBDD.Framework.Scenarios.Basic
    • BasicScenarioExtensions allowing to call scenarios with basic scenario format Runner.RunScenario(Given_...)
  • LightBDD.Framework.Scenarios.Extended
    • ExtendedScenarioExtensions allowing to call scenario with extended scenario format Runner.RunScenario(_ => Given_...)
  • LightBDD.Framework.Scenarios.Contextual
    • ContextualScenarioExtensions allowing to call Runner.WithContext(...)
  • LightBDD.XUnit2
    • FeatureFixture
    • FeatureFixtureAttribute
    • LightBddScopeAttribute
    • ScenarioAttribute
    • StepExecutionExtensions allowing to call StepExecution.Current.IgnoreScenario(...)
  • LightBDD.NUnit3
    • FeatureFixture
    • FeatureFixtureAttribute
    • LightBddScopeAttribute
    • ScenarioAttribute
  • LightBDD.NUnit2
    • FeatureFixture
    • FeatureFixtureAttribute
    • LightBddScopeAttribute
    • ScenarioAttribute
  • LightBDD.MsTest2
    • FeatureFixture
    • FeatureFixtureAttribute
    • LightBddScope
    • ScenarioAttribute

Please note that less commonly used types are not listed here - please use Intellisense or tools like Resharper or browse the LightBDD code to locate them, or ask on project issues page for details.

Migrating tests to scenarios

With LightBDD 2, the ScenarioAttribute has been introduced which replaces the underlying test framework attribute(s) used to annotate the test methods. The presence of that attribute is needed to properly integrate LightBDD scenario execution with the test runner, so that the regular test framework attributes such as NUnit [Test] / MsTest [TestMethod] / XUnit [Fact] and [Theory] are not supported. An attempt to execute LightBDD scenario from method not annotated with [Scenario] attribute will fail with exception.

Adding LightBDD scope

The LightBDD 2 requires its explicit initialization and cleanup in the test assembly to allow framework configuration on startup and reports generation after all tests. The 1.x series were performing such operations behind the scenes, but mechanisms used for that were not portable to all modern platforms and flexible for customization (configuration from app.config) or not reliable (report generation)

The following code samples show how to add LightBDD scope to the tests projects:

  • LightBDD.NUnit3

    [assembly: LightBddScope]
  • LightBDD.NUnit2

    [assembly: LightBddScope]
  • LightBDD.XUnit2

    [assembly: LightBddScope]
  • LightBDD.MsTest2

    [TestClass]
    public class LightBddIntegration
    {
        [AssemblyInitialize]
        public static void Setup(TestContext testContext) { LightBddScope.Initialize(); }
        [AssemblyCleanup]
        public static void Cleanup() { LightBddScope.Cleanup(); }
    }

Please note that in 1.x series it was necessary to add either [assembly: Debuggable(true, true)] to the assembly or [MethodImpl(MethodImplOptions.NoInlining)] to the test method to properly display the scenario names in Release mode. In 2.x series such limitation no longer exists and such attributes can be removed.

Migrating configuration

The LightBDD configuration is done now in code, during LightBDD scope initialization.

The following code samples shows 1.x sample configuration and 2.x equivalent. Please note that the default names of the report files have changed from FeaturesSummary.* to FeaturesReport.*.

The LightBDD 1.x configuration:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="lightbdd" type="LightBDD.Configuration.LightBDDConfiguration, LightBDD"/>
  </configSections>
  <lightbdd>
    <summaryWriters type="LightBDD.SummaryGeneration.FormattableSummaryFileWriter, LightBDD">
      <clear />
      <add formatter="LightBDD.Results.Formatters.PlainTextResultFormatter, LightBDD" output="~\Reports\FeaturesSummary.txt"/>
      <add formatter="LightBDD.Results.Formatters.HtmlResultFormatter, LightBDD" output="~\Reports\FeaturesSummary.html"/>
      <add formatter="LightBDD.Results.Formatters.XmlResultFormatter, LightBDD" output="~\Reports\{TestDateTimeUtc:yyyy-MM-dd-HH_mm_ss}_FeaturesSummary.xml"/>
    </summaryWriters>
    <stepTypes predefined="given,when,then,but" repeatedStepReplacement="and also"/>
  </lightbdd>
</configuration>

The LightBDD 2.x equivalent (LightBDD.NUnit3):

using LightBDD.Core.Configuration;
using LightBDD.Framework.Reporting.Configuration;
using LightBDD.Framework.Reporting.Formatters;
using LightBDD.NUnit3;
using MyNamespace;

[assembly: ConfiguredLightBddScope]
namespace MyNamespace
{
    class ConfiguredLightBddScopeAttribute : LightBddScopeAttribute
    {
        protected override void OnConfigure(LightBddConfiguration configuration)
        {
            configuration
                .ReportWritersConfiguration()
                .Clear()
                .AddFileWriter<PlainTextReportFormatter>("~\\Reports\\FeaturesReport.txt")
                .AddFileWriter<HtmlReportFormatter>("~\\Reports\\FeaturesReport.html")
                .AddFileWriter<XmlReportFormatter>("~\\Reports\\{TestDateTimeUtc:yyyy-MM-dd-HH_mm_ss}_FeaturesReport.xml");

            configuration
                .StepTypeConfiguration()
                .UpdatePredefinedStepTypes("given", "when", "then", "but")
                .UpdateRepeatedStepReplacement("and also");
        }
    }
}

The LightBDD 2.x equivalent (LightBDD.NUnit2):

using LightBDD.Core.Configuration;
using LightBDD.Framework.Reporting.Configuration;
using LightBDD.Framework.Reporting.Formatters;
using LightBDD.NUnit2;
using MyNamespace;

[assembly: ConfiguredLightBddScope]
namespace MyNamespace
{
    class ConfiguredLightBddScopeAttribute : LightBddScopeAttribute
    {
        protected override void OnConfigure(LightBddConfiguration configuration)
        {
            configuration
                .ReportWritersConfiguration()
                .Clear()
                .AddFileWriter<PlainTextReportFormatter>("~\\Reports\\FeaturesReport.txt")
                .AddFileWriter<HtmlReportFormatter>("~\\Reports\\FeaturesReport.html")
                .AddFileWriter<XmlReportFormatter>("~\\Reports\\{TestDateTimeUtc:yyyy-MM-dd-HH_mm_ss}_FeaturesReport.xml");

            configuration
                .StepTypeConfiguration()
                .UpdatePredefinedStepTypes("given", "when", "then", "but")
                .UpdateRepeatedStepReplacement("and also");
        }
    }
}

The LightBDD 2.x equivalent (LightBDD.XUnit2):

using LightBDD.Core.Configuration;
using LightBDD.Framework.Reporting.Configuration;
using LightBDD.Framework.Reporting.Formatters;
using LightBDD.XUnit2;
using MyNamespace;

[assembly: ConfiguredLightBddScope]
namespace MyNamespace
{
    class ConfiguredLightBddScopeAttribute : LightBddScopeAttribute
    {
        protected override void OnConfigure(LightBddConfiguration configuration)
        {
            configuration
                .ReportWritersConfiguration()
                .Clear()
                .AddFileWriter<PlainTextReportFormatter>("~\\Reports\\FeaturesReport.txt")
                .AddFileWriter<HtmlReportFormatter>("~\\Reports\\FeaturesReport.html")
                .AddFileWriter<XmlReportFormatter>("~\\Reports\\{TestDateTimeUtc:yyyy-MM-dd-HH_mm_ss}_FeaturesReport.xml");

            configuration
                .StepTypeConfiguration()
                .UpdatePredefinedStepTypes("given", "when", "then", "but")
                .UpdateRepeatedStepReplacement("and also");
        }
    }
}

The LightBDD 2.x equivalent (LightBDD.MsTest2):

using LightBDD.Core.Configuration;
using LightBDD.Framework.Reporting.Configuration;
using LightBDD.Framework.Reporting.Formatters;
using LightBDD.MsTest2;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MyNamespace
{
    [TestClass]
    public class LightBddIntegration
    {
        [AssemblyInitialize]
        public static void Setup(TestContext testContext) { LightBddScope.Initialize(OnConfigure); }
        [AssemblyCleanup]
        public static void Cleanup() { LightBddScope.Cleanup(); }

        private static void OnConfigure(LightBddConfiguration configuration)
        {
            configuration
                .ReportWritersConfiguration()
                .Clear()
                .AddFileWriter<PlainTextReportFormatter>("~\\Reports\\FeaturesReport.txt")
                .AddFileWriter<HtmlReportFormatter>("~\\Reports\\FeaturesReport.html")
                .AddFileWriter<XmlReportFormatter>("~\\Reports\\{TestDateTimeUtc:yyyy-MM-dd-HH_mm_ss}_FeaturesReport.xml");

            configuration
                .StepTypeConfiguration()
                .UpdatePredefinedStepTypes("given", "when", "then", "but")
                .UpdateRepeatedStepReplacement("and also");
        }
    }
}

Migrating StepExecution methods

The StepExecution class has been changed:

  • it provides Current static property to allow adding extension methods to the class,
  • its static methods has become instance ones or has been made extension methods.

The following list shows StepExecution equivalents between LightBDD 1.x and 2.x:

  • Bypassing
    1.x: StepExecution.Bypass(...)
    2.x: StepExecution.Current.Bypass(...)
    2.x namespace: LightBDD.Framework
  • Commenting
    1.x: StepExecution.Comment(...)/StepExecution.CommentFormat(...)
    2.x: StepExecution.Current.Comment(...)
    2.x namespace: LightBDD.Framework.Commenting
  • Ignoring scenario (LightBDD.XUnit2)
    1.x: ScenarioAssert.Ignore(...)
    2.x: StepExecution.Current.IgnoreScenario(...)
    2.x namespace: LightBDD.XUnit2

Migrating scenarios

The scenario runner class has been reworked in 2.x series. While in LightBDD 1.x it was an AbstractBDDRunner class offering a combination of all methods to run scenarios, the LightBDD 2.x series offers an IBddRunner interface with a set of extension methods allowing to execute scenarios.

The new runner mechanism has been designed in a way to:

  • allow easily extending runner capabilities with extension methods (where those methods are separated with namespaces suggesting their purpose),
  • allow composing scenario behaviors in fluent manner (separated scenario context creation from scenario step execution syntax),
  • separate methods dedicated for end-users from lower level methods that should be used by integration projects.

Below there is the comparison between 1.x and 2.x runner methods:

  • basic
    1.x: RunScenario(Given_...,When_...)
    2.x: RunScenario(Given_...,When_...)
    Notes: no changes
  • extended
    1.x: RunScenario(_ => Given_...("text"), _ => When_...())
    2.x: RunScenario(_ => Given_...("text"), _ => When_...())
    Notes: no changes
  • extended
    1.x: RunScenario(given => ...(), when => ...())
    2.x: RunScenario(given => ...(), when => ...())
    Notes: no changes
  • contextual
    1.x: RunScenario<...>(...)
    2.x: WithContext<...>().RunScenario(...)
    Notes: see next section for more details
  • fluent
    1.x: NewScenario()
    2.x: not present
    Notes: this method has been removed and one of the methods above should be used instead, or custom scenario format should be created.
  • explicit
    1.x: RunScenario("name", "label")
    2.x: not present
    Notes: those methods have been removed as they were too low-level (the test metadata should be detected by the runner) - if really needed, the custom scenario format should be created
  • properties
    1.x: ProgressNotifier/Result
    2.x: not present
    Notes: those properties have been removed as they were not meant to be used by end-users.

Please note that it is possible to implement custom scenario formats if needed and use Integrate() extension method on the runner to access more low-level methods (the basic scenario format is a good example how it works). Please also feel free to contact if it would be beneficial to include the new extensions in LightBDD packages.

Migrating contextual scenario tests

The extended scenarios created in LightBDD 1.x series have to be migrated to LightBDD 2.x as the context definition has been separated from scenario running and the scenario syntax has been simplified. In LightBDD 2.x there is only one lambda parameter that allows to access scenario context instance and define step type.

LightBDD 1.x scenario:

Runner.RunScenario<SpeditionContext>(
    (given, ctx) => ctx.There_is_an_active_customer_with_id("ABC-123"),
    (and, ctx) => ctx.The_customer_has_product_in_basket("wooden shelf"),
    (and, ctx) => ctx.The_customer_has_product_in_basket("wooden desk"),
    (when, ctx) => ctx.The_customer_payment_finalizes(),
    (then, ctx) => ctx.Product_should_be_dispatched_to_the_customer("wooden shelf"),
    (and, ctx) => ctx.Product_should_be_dispatched_to_the_customer("wooden desk"));

LightBDD 2.x scenario equivalent:

Runner.WithContext<SpeditionContext>().RunScenario(
    given => given.There_is_an_active_customer_with_id("ABC-123"),
    and => and.The_customer_has_product_in_basket("wooden shelf"),
    and => and.The_customer_has_product_in_basket("wooden desk"),
    when => when.The_customer_payment_finalizes(),
    then => then.Product_should_be_dispatched_to_the_customer("wooden shelf"),
    and => and.Product_should_be_dispatched_to_the_customer("wooden desk"));

or

Runner.WithContext<SpeditionContext>().RunScenario(
    _ => _.Given_there_is_an_active_customer_with_id("ABC-123"),
    _ => _.Given_the_customer_has_product_in_basket("wooden shelf"),
    _ => _.Given_the_customer_has_product_in_basket("wooden desk"),
    _ => _.When_the_customer_payment_finalizes(),
    _ => _.Then_product_should_be_dispatched_to_the_customer("wooden shelf"),
    _ => _.Then_product_should_be_dispatched_to_the_customer("wooden desk"));

Please note that LightBDD.Framework.Scenarios.Extended and LightBDD.Framework.Scenarios.Contextual namespaces have to be added to access those extension methods.

The basic scenarios (from LightBDD.Framework.Scenarios.Basic namespace) does not support contextual scenarios any more - those tests have to be converted to extended scenario format (the functionality may be restored upon request).

Uncovered changes

In case of migration issues please browse the LightBDD examples code to see how projects looks with LightBDD 2, or ask on project issues page for details. In case of any functionality missing in LightBDD version 2, please feel free to ask on project issues page.

Continue reading: Scenario state management

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.