是否可以以编程方式向场景添加行?

2024-01-14

我想在每个 SpecFlow 测试的开头添加相同的行。

这一行指定了几个场景的列表,这些场景会随着时间的推移而改变,因此为每个测试维护这个列表是不可行的。

例如:

Given I have set my site theme to <MyTheme>
    |Theme Names|
    |Theme 1    |
    |Theme 2    |
    |Theme 3    |
    |Theme 4    |
    |Theme 5    |

我想对每个主题重复这个测试。主题列表不是一成不变的,应该保存在一个地方。

到目前为止,我已经成功创建了一个Generator Plugin,我计划在生成测试类之前立即使用此插件来更改 SpecFlow 功能。但是,我看不到在此上下文中编辑场景的方法。

是否可以从以下实现中获取和设置场景文本IUnitTestGeneratorProvider?

我不打算使用这种方法,所以如果有人能提出更好的方法来做到这一点,那么我也会接受。

如果我弄错了一些术语,请道歉 - 我才刚刚开始使用 SpecFlow。

Edit:

我添加此部分是为了澄清我实际想要的内容。

假设我有一个包含 800 个测试的测试套件。我们的业务要求是对每个可用主题运行这 800 个测试。可用主题列表可以随时更改,并且在多个位置维护此列表是不可行的。

例如,如果我有以下两个测试:

示例A:

    Given I set context to < site >
    Given I go to base url
    When I type <username> in username field
    When I type <password> in password field
    When I click login button
    Examples:
        | site         | username  | password   |
        | MySuperSite  | chris     | mypassword |
        | MySuperSite2 | chris2    | mypassword |



    Given I am logged in
    Given I go to base url
    When I click logout button
    Then I am logged out

我可以简单地手动将这些测试更改为以下内容:

示例B:

    Given I am using the < theme > theme
    Given I set context to < site >
    Given I go to base url
    When I type <username> in username field
    When I type <password> in password field
    When I click login button
    Examples:
        | site         | username  | password   | theme  |
        | MySuperSite  | chris     | mypassword | theme1 |
        | MySuperSite2 | chris2    | mypassword | theme1 |
        | MySuperSite  | chris     | mypassword | theme2 |
        | MySuperSite2 | chris2    | mypassword | theme2 |
        | MySuperSite  | chris     | mypassword | theme3 |
        | MySuperSite2 | chris2    | mypassword | theme3 |



    Given I am using the < theme > theme
    Given I am logged in
    Given I go to base url
    When I click logout button
    Then I am logged out
    Examples:
        | theme  |
        | theme1 |
        | theme2 |
        | theme3 |

这有几个问题:

  • 测试因重复的数据而变得臃肿
  • 如果我们不再选择支持theme2然后有人必须完成每个测试并将其从示例表中删除(在上面的示例中还不错,但想象一下我们有超过 800 个测试)
  • 已经具有示例表的测试将其表大小乘以我们支持的主题数量(> 40)
  • 由于某人无意中忘记将特定主题添加到测试而导致手动错误的风险很大

客观的:我希望能够让我们的测试人员以以下风格编写测试Example A,但是让测试本身编译成如果它们是以以下风格编写的Example B.

我为 Specflow 创建了一个生成器插件,旨在拦截测试创建,然后以编程方式添加该行Given I am using the < theme > theme,然后根据需要更新或添加任何示例数据。但是,我似乎无法从这里做到这一点。

谁能告诉我这是否可能,如果可以,我该怎么做?


好吧,我明白了。花了几个步骤:

在查看了GitHub上的源代码后,我发现UnitTestFeatureGenerator它似乎是负责将规范流文件转换为单元测试的类。

然后我创建了一个继承自的新类UnitTestFeatureGenerator并隐藏GenerateUnitTestFixture来自基类的方法。

在我的身体里GenerateUnitTestFixture类,然后我在交接之前将所需的额外步骤添加到场景中base.GenerateUnitTestFixture生成单元测试。这是它的要点:

public class MultiThemeUnitTestFeatureGenerator : UnitTestFeatureGenerator, IFeatureGenerator
{
    public MultiThemeUnitTestFeatureGenerator(IUnitTestGeneratorProvider testGeneratorProvider, CodeDomHelper codeDomHelper, GeneratorConfiguration generatorConfiguration, IDecoratorRegistry decoratorRegistry)
        : base(testGeneratorProvider, codeDomHelper, generatorConfiguration, decoratorRegistry)
    {}

    public new CodeNamespace GenerateUnitTestFixture(Feature feature, string testClassName, string targetNamespace)
    {
        foreach (var scenario in feature.Scenarios)
        {
            scenario.Steps.Insert(0, new Given {Text = "Given I have <Theme> set as my current theme"});

            //add any other steps you need....
        }

        return base.GenerateUnitTestFixture(feature, testClassName, targetNamespace);
    }
}

一旦我完成了所有这些设置,我需要一种方法来告诉specflow使用我的新类而不是当前注册的类UnitTestFeatureGenerator。这是一个复杂的工作,因为文档几乎只是说“即将推出”。值得庆幸的是,我找到了一篇出色的博客文章,其中概述了所有陷阱。 https://jessehouwing.net/specflow-custom-unit-test-generator/

My IGeneratorPlugin实现看起来像这样:

public class MultiThemeGeneratorPlugin : IGeneratorPlugin
{
    public void RegisterDependencies(ObjectContainer container)
    {}

    public void RegisterCustomizations(ObjectContainer container, SpecFlowProjectConfiguration generatorConfiguration)
    {
        container.RegisterTypeAs<MultiThemeFeatureGeneratorProvider, IFeatureGeneratorProvider>("default");
    }

    public void RegisterConfigurationDefaults(SpecFlowProjectConfiguration specFlowConfiguration)
    {}
}

注意我注册了IFeatureGeneratorProvider相对于IFeatureGenerator。我必须创建一个实现IFeatureGeneratorProvider返回一个实现的实例IFeatureGenerator我感兴趣的是:

public class MultiThemeFeatureGeneratorProvider : IFeatureGeneratorProvider
{
    private readonly ObjectContainer _container;

    public MultiThemeFeatureGeneratorProvider(ObjectContainer container)
    {
        _container = container;
    }

    public int Priority
    {
        get { return int.MaxValue; }
    }

    public bool CanGenerate(Feature feature)
    {
        return true;
    }

    public IFeatureGenerator CreateGenerator(Feature feature)
    {
        return _container.Resolve<MultiThemeUnitTestFeatureGenerator>();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以以编程方式向场景添加行? 的相关文章

随机推荐