在SpecFlow中实现后台步骤的正确方法

问题描述 投票:1回答:1

我目前正在学习使用SpecFlow,并希望编写一个功能,其中包括注册用户的测试。

我有第一个测试用例,注册一个有效用户。这将涉及输入用户名,电子邮件,密码和确认密码。单击“提交”,应注册用户并将其添加到数据库。

我的下一个测试用例将是一个无效的情况,我将执行上述步骤,然后尝试注册具有相同用户名的用户,这应该返回错误。根据我可以从我发现的示例中理解,我可以在.feature文件中使用“Background”来指定我想在.feature文件中的每个场景之前执行的步骤。这将涉及在Background部分中创建一个步骤来注册用户并调用在Valid Register User case中创建的方法。这个question对我有所帮助,但也为我提出了更多问题,因为我无法理解可用的标签和挂钩的正确用法。

我的问题是:

  1. 有效测试用例是否应与其他方案位于同一文件中?如果为该功能文件中的每个方案调用Background部分,那么它将导致有效测试失败(因为它本质上是有效的测试用例)
  2. 这是构建测试的正确方法吗?我已经阅读了可以使用[BeforeScenario] / [AfterScenario]等的SpecFlow挂钩,但是我不确定何时应该在Background标签上考虑这些挂钩。
  3. 我觉得有很多重复可以避免,例如只是将有效的测试用例作为另一个测试中的一个步骤,而不是为它创建一个步骤以及测试用例,但也许这就是SpecFlow的方法。应该工作,是吗?

到目前为止,对于这个测试用例,我在.feature文件中有以下内容。

    Feature: RegisterUser
    In order to register a user successfully
    A valid username, email, password (and confirmation password) must be entered


@register
Scenario: Valid Register User
    Given I have entered a username "testing", an email "[email protected]", a password "123456" and a confirmation password "123456"
    When I press submit
    Then the response code should be 200
    And the user should be added to the database with verfied set to False

Background: 
    Given I have registered a user "testing", "[email protected]", "123456" and "123456"

@register
Scenario: Username Already Taken
    Given I have entered a username "testing", an email "[email protected]", a password "123456" and a confirmation password "123456"
    When I press submit
    Then the response code should be 400

我的步骤文件是这样的:

using NUnit.Framework;
using System;
using System.Net.Http;
using TechTalk.SpecFlow;

namespace Tests.Specs
{
[Binding]
public class RegisterUserSteps
{
    private RegisterUserModel userInfo = new RegisterUserModel();
    private RegisterUserController user = new RegisterUserController()
    {
        Request = new HttpRequestMessage(),
        Configuration = new System.Web.Http.HttpConfiguration()
    };
    private ApiResponse response = new ApiResponse();
    private static string userTableName = "usersTable";
    private static string userTablePartitionKey = "USER_INFO";
    private static string userTableRowKey = "[email protected]";


    [Given(@"I have entered a username ""(.*)"", an email ""(.*)"", a password ""(.*)"" and a confirmation password ""(.*)""")]
    public void GivenIHaveEnteredAUsernameAnEmailAPasswordAndAConfirmationPassword(string p0, string p1, string p2, string p3)
    {
        userInfo.Username = p0;
        userInfo.Email = p1;
        userInfo.Password = p2;
        userInfo.ConfirmPassword = p3;
    }

    [When(@"I press submit")]
    public void WhenIPressSubmit()
    {
        response = user.Register(userInfo);
    }

    [Then(@"the response code should be (.*)")]
    public void ThenTheResponseCodeShouldBe(int p0)
    {
        Assert.AreEqual(p0, response.Status);
    }


    [Then(@"the user should be added to the database with verfied set to False")]
    public void ThenTheUserShouldBeAddedToTheDatabaseWithVerfiedSetToFalse()
    {
        UserEntity user = AzureUtilities.RetrieveEntity<UserEntity>(userTableName, userTablePartitionKey, userTableRowKey);
        Assert.IsNotNull(user);
        Assert.AreEqual(userInfo.Username, user.Username);
        Assert.AreEqual(userInfo.Email, user.RowKey);
        Assert.IsFalse(user.Verified);
    }

    [Given(@"I have registered a user ""(.*)"", ""(.*)"", ""(.*)"" and ""(.*)""")]
    public void GivenIHaveRegisteredAUserAnd(string p0, string p1, string p2, string p3)
    {
        //Using methods here that have been defined in previous steps
        GivenIHaveEnteredAUsernameAnEmailAPasswordAndAConfirmationPassword(p0, p1, p2, p3);
        WhenIPressSubmit();
        ThenTheResponseCodeShouldBe(200);
    }
c# visual-studio specflow gherkin feature-file
1个回答
1
投票

我认为你正试图跳转到使用背景而不实际拥有在你的场景中常见的东西。

SpecFlow非常强大,只要您为步骤创建一致的结构,就可以重复使用很多步骤。

让我们从您的功能开始吧。此功能类似于开发人员脚本。功能应该代表一些业务目标。忍受我,因为我不知道你的业务目标是什么

Feature: Register New Users
    In order to perform task that only registered users can do
    As a web site user
    I want to register for the site

既然我们知道为什么要编写代码,我们就可以开始设置方案来实现这一点。

Given I am not registered for the site
And I have filled out the registration form as follows
| Field                 | Value             |
| username              | testing           |
| email                 | [email protected] |
| password              | 123456            |
| password confirmation | 123456            |
When I submit the registration
Then the response code should be '200'
And the database should have an unverified user

这会创建一些sstepscenarios,但是您将立即重用,因为您现在传递变量以填写注册表单并检查响应代码。

所以现在你已经采用的用户名场景可以改为

Scenario: Username taken
Given a user has registered with the following information
| Field                 | Value             |
| username              | testing           |
| email                 | [email protected] |
| password              | 123456            |
| password confirmation | 123456            |
And I have filled out the registration form as follows
| Field                 | Value             |
| username              | testing           |
| email                 | [email protected] |
| password              | 123456            |
| password confirmation | 123456            |
When I submit the registration
Then the response code should be '400'

所以现在你需要实现的唯一步骤是第一步

鉴于用户已注册以下信息

由于步骤只是代码,因此您可以从第一个场景中调用已定义的步骤

    [Given(@"a user has registered with the following information")]
    public void GivenAUserHasRegisteredWithTheFollowingInformation(Table table)
    {
        GivenIHaveFilledOutTheRegistrationFormAsFollows(table);
        WhenISubmitTheRegistration();
        ThenTheResponseCodeShouldBe(200)
    }

至于Hooks,我将它们用于更多技术方面。我在使用Selenium的测试中做了很多。我创建了一个钩子@web,它在场景之前运行以启动Selenium并在场景完成后将其拆除。我已经对API测试做了同样的事情,也许你想在场景之前启动一个HttpClient,然后撕下来。在实际开始测试之前,您还可以执行清除数据库或清除和播种到已知状态的操作。

我希望这能回答你所有的问题。

© www.soinside.com 2019 - 2024. All rights reserved.