Tests library for Bot Framework dialogs XUnit tests
Branch: master
Clone or download
Latest commit fbe6f0b Feb 19, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Objectivity.Bot.Tests.Stories.Xunit.Sample CI improvments: Dec 11, 2018
Objectivity.Bot.Tests.Stories.Xunit Set GeneratePackageOnBuild to false Feb 19, 2019
.gitignore Include git ignore, analyzers and appveyor Oct 18, 2017
Analysers.Tests.ruleset CI improvments: Dec 11, 2018
Analysers.ruleset CI improvments: Dec 11, 2018
Bot.Tests.Stories.Xunit.sln Describe package in csproj, remove unused nuspec file Dec 22, 2017
Bot.Tests.Stories.Xunit.sln.DotSettings Fix unit test story player to handle properly bot-initiated dialogs, … Dec 21, 2017
CustomDictionary.xml
CustomDictionaryTests.xml Fix unit test story player to handle properly bot-initiated dialogs, … Dec 21, 2017
LICENSE Initial commit Oct 18, 2017
README.md Move text to a new line after badges Dec 11, 2018
appveyor.yml Handle repo tags when preparing nuget package Feb 13, 2019

README.md

Bot.Tests.Stories.Xunit

Build Status Tests Status codecov License: MIT

Tests library for Bot Framework dialogs using XUnit and Objectivity Test Stories.

Note

This project is still a work in progress, all contributions from your site will be very desirable!

Installation

You can install the package using the nuget:

Install-Package Objectivity.Bot.Tests.Stories.Xunit

Limitations

At the moment test base classes are permitted only for dialogs returning object type. Story recorder used in this library does not allow to recognize user identity during conversation test.

Usage

Simple dialogs

To develop a unit test for a dialog, create new test class inheriting from Objectivity.Bot.Tests.Stories.Xunit.DialogUnitTestBase<T> class, providing your dialog Type as generic parameter. Then for each test please go through the following steps:

  • Record a story
  • Rewind
  • Play (assert)

Example:

public class EchoDialogTests : DialogUnitTestBase<EchoDialog>
{
    [Fact]
    public async Task HelloTest()
    {
        var story = StoryRecorder
            .Record()
            .User.Says("Hello")
            .Bot.Says("You said Hello")
            .Rewind();

        await this.Play(story);
    }
}

Dialog with prompts

You can use specialized method for dialogs with prompts:

public class PropmtDialogTests : DialogUnitTestBase<PropmtDialog>
{
    [Fact]
    public async Task HelloTest()
    {
        var story = StoryRecorder
            .Record()
            .Bot.Confirms("Are you enjoying this conversation?")
            .User.Says("Yes")
            .Bot.GivesChoice(
                "Who is a better conversationalist?",
                new[] { "Bot", "Real person", "Rubber duck" })
            .User.Says("Bot")
            .Bot.Says("Thank you")
            .Rewind();

        await this.Play(story);
    }
}

Dialog finish scenarios

You can also define various dialog finish scenarios.

Dialog Done

The example below assumes the Dialog calls context.Done() after bot posts first reply.

public class MyDialogTests : DialogUnitTestBase<MyDialog>
{
    [Fact]
    public async Task HelloTest()
    {
        var story = StoryRecorder
            .Record()
            .User.Says("Hi")
            .Bot.Says("Good bye")
            .DialogDone();

        await this.Play(story);
    }
}

Dialog Done with result predicate

The example below assumes the Dialog calls context.Done(true) after bot posts first reply.

public class MyDialogTests : DialogUnitTestBase<MyDialog>
{
    [Fact]
    public async Task HelloTest()
    {
        var story = StoryRecorder
            .Record()
            .User.Says("Hi")
            .Bot.Says("Good bye")
            .DialogDoneWithResult<bool>(result => result == true);

        await this.Play(story);
    }
}

Dialog Failed

The example below assumes the Dialog calls context.Fail(ex) with any kind of exception after first user sentence.

public class MyDialogTests : DialogUnitTestBase<MyDialog>
{
    [Fact]
    public async Task HelloTest()
    {
        var story = StoryRecorder
            .Record()
            .Bot.Says("Type a number:")
            .User.Says("Ok")
            .DialogFailed();

        await this.Play(story);
    }
}

Dialog Failed with expected exception type

The example below assumes the Dialog calls context.Fail(ex) with specific kind of exception after first user sentence.

public class MyDialogTests : DialogUnitTestBase<MyDialog>
{
    [Fact]
    public async Task HelloTest()
    {
        var story = StoryRecorder
            .Record()
            .Bot.Says("Type a number:")
            .User.Says("Ok")
            .DialogFailedWithExceptionOfType<FormatException>();

        await this.Play(story);
    }
}

LUIS dialogs

To develop a unit test for a LUIS dialog (inheriting LuisDialog<object> class), create new test class inheriting from Objectivity.Bot.Tests.Stories.Xunit.LuisDialogUnitTestBase<T> class, providing your dialog Type as generic parameter. Then for each test please go through the following steps:

  • Register utterance (for intent test)
  • Record a story
  • Rewind
  • Play (assert)

Example:

public class EchoDialogTests : LuisDialogUnitTestBase<EchoDialog>
{
    [Fact]
    public async Task HelloTest()
    {
        var story = StoryRecorder
            .Record()
            .User.Says("Hello")
            .Bot.Says("You said Hello")
            .Rewind();

        await this.Play(story);
    }
}

Injecting dependencies

If your dialog requires some dependencies injected using Autofac, you can provide them by overloading RegisterAdditionalTypes protected method. Example:

protected override void RegisterAdditionalTypes(ContainerBuilder builder)
{
    builder.RegisterType<EchoService>().As<IEchoService>();
}