65.9K
CodeProject 正在变化。 阅读更多。
Home

测试架构设计评估系统 - 基于行为的测试

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2017年3月27日

Ms-PL

5分钟阅读

viewsIcon

5275

我们将使用之前介绍的评估框架来评估使用行为模式的测试。找到相应的评分和理由。

引言

在我之前的文章《测试架构设计的评估系统》中,我向大家介绍了八个用于测试架构设计的评估标准。为了更全面地理解该系统,我将用它来评估几个实际示例,为每个标准进行评分,并解释我的理由。我们将要评估的第二类测试是基于行为的测试(乐高式测试)。如果您不熟悉行为设计模式(乐高设计模式),可以阅读我的文章《自动化测试中的高级行为设计模式(第二部分)》。

基于行为的测试

抽象行为

public abstract class WaitableActionBehaviour : IBehaviour
{
    public void Execute()
    {
        this.PerformAct();
        this.PerformPostActWait();
    }

    protected abstract void PerformAct();

    protected abstract void PerformPostActWait();
}

通常,一个行为会执行一个页面特定的工作流程——执行操作并等待一个条件。行为有不同的类型——仅操作、仅断言、两者结合或添加额外的预/后等待条件(等待页面加载或等待元素可见)。上面是所有行为的基类,它首先执行操作,然后等待某事发生。

具体行为

public class PreviewShoppingCartPageProceedBehaviour : WaitableActionBehaviour
{
    private readonly PreviewShoppingCartPage previewShoppingCartPage;
    private readonly SignInPage signInPage;

    public PreviewShoppingCartPageProceedBehaviour()
    {
        this.previewShoppingCartPage = 
        UnityContainerFactory.GetContainer().Resolve<PreviewShoppingCartPage>();
        this.signInPage = 
        UnityContainerFactory.GetContainer().Resolve<SignInPage>(); 
    }

    protected override void PerformAct()
    {
        this.previewShoppingCartPage.ClickProceedToCheckoutButton();
    }

    protected override void PerformPostActWait()
    {
        this.signInPage.WaitForPageToLoad();
    }
}

特定行为的具体实现不必重写基类的所有方法(如果存在后/预等待和断言方法,则类可以只重写其中一个)。行为会持有所有依赖页面或其他服务的私有实例。它们通过 Unity IoC 容器在行为的构造函数中初始化。

带参数的行为

public class ShippingAddressPageFillDifferentBillingBehaviour : ActionBehaviour
{
    private readonly ShippingAddressPage shippingAddressPage;
    private readonly ShippingPaymentPage shippingPaymentPage;
    private readonly PerfectSystemTestsDesign.Data.ClientPurchaseInfo clientPurchaseInfo;

    public ShippingAddressPageFillDifferentBillingBehaviour(ClientPurchaseInfo clientPurchaseInfo)
    {
        this.shippingAddressPage = UnityContainerFactory.GetContainer().Resolve<ShippingAddressPage>();
        this.shippingPaymentPage = UnityContainerFactory.GetContainer().Resolve<ShippingPaymentPage>();
        this.clientPurchaseInfo = clientPurchaseInfo;
    }

    protected override void PerformAct()
    {
        this.shippingAddressPage.ClickDifferentBillingCheckBox(this.clientPurchaseInfo);
        this.shippingAddressPage.ClickContinueButton();
        this.shippingPaymentPage.ClickBottomContinueButton();
        this.shippingAddressPage.FillBillingInfo(this.clientPurchaseInfo);
    }
}

如果需要,特定的行为可以接受自定义参数。

测试中的行为使用

[TestMethod]
public void Purchase_SimpleBehaviourEngine()
{
    var itemUrl = "/Selenium-Testing-Cookbook-Gundecha-Unmesh/dp/1849515743";
    var itemPrice = "40.49";
    var clientPurchaseInfo = new ClientPurchaseInfo(
        new ClientAddressInfo()
        {
            FullName = "John Smith",
            Country = "United States",
            Address1 = "950 Avenue of the Americas",
            State = "New York",
            City = "New York City",
            Zip = "10001-2121",
            Phone = "00164644885569"
        });
    clientPurchaseInfo.CouponCode = "99PERDIS";
    var clientLoginInfo = new ClientLoginInfo()
    {
        Email = "g3984159@trbvm.com",
        Password = "ASDFG_12345"
    };
    PerfectSystemTestsDesign.Behaviours.Core.BehaviourExecutor.Execute(
        new ItemPageNavigationBehaviour(itemUrl),
        new ItemPageBuyBehaviour(),
        new PreviewShoppingCartPageProceedBehaviour(),
        new SignInPageLoginBehaviour(clientLoginInfo),
        new ShippingAddressPageFillShippingBehaviour(clientPurchaseInfo),
        new ShippingAddressPageFillDifferentBillingBehaviour(clientPurchaseInfo),
        new ShippingAddressPageContinueBehaviour(),
        new ShippingPaymentPageContinueBehaviour(),
        new PlaceOrderPageAssertFinalAmountsBehaviour(itemPrice));
}

行为被添加到一个特殊的行为执行器列表中,该执行器负责以适当的方式执行它们。如果行为依赖于任何数据,则在传递给其构造函数时提供。

行为设计模式的优点

  • 可读性强
  • 可以详细查看工作流程的步骤

如果您不想执行某些断言的微型工作流程,只需不将其行为包含在列表中即可。遵循最小知识原则,因为您只将所需数据传递给行为的构造函数。

行为设计模式的缺点

引入了大量新类。编写新测试的速度变慢,因为现在需要初始化所有必需的行为。测试编写过程更容易出错,因为您可能会弄错步骤顺序或为某些行为参数分配错误的值。

评估基于行为的测试——评估系统

可维护性

[Binding]
public class SignInPageLoginBehaviour : WaitableActionBehaviour
{
    private readonly SignInPage signInPage;
    private readonly ShippingAddressPage shippingAddressPage;
    private ClientLoginInfo clientLoginInfo;

    public SignInPageLoginBehaviour()
    {
        this.signInPage = 
            UnityContainerFactory.GetContainer().Resolve<SignInPage>();
        this.shippingAddressPage = 
            UnityContainerFactory.GetContainer().Resolve<ShippingAddressPage>(); 
    }

    [When(@"I login with email = ""([^""]*)"" and pass = ""([^""]*)""")]
    public void LoginWithEmailAndPass(string email, string password)
    {
        this.clientLoginInfo = new ClientLoginInfo
        {
            Email = email,
            Password = password
        };
        base.Execute();
    }

    protected override void PerformPostActWait()
    {
        this.shippingAddressPage.WaitForPageToLoad();
    }

    protected override void PerformAct()
    {
        this.signInPage.Login(this.clientLoginInfo.Email, this.clientLoginInfo.Password);
    }
}

可维护性评为优秀(5)。行为是某些用例的微型工作流程。如果用例需要更改,只需在此处编辑。由于行为仅按需添加,因此并非对所有情况都执行。如果您修复了一个行为,更改将仅影响使用它的测试。

 基于行为的测试
可维护性5
可读性 
代码复杂度指数 
可用性 
灵活性 
学习曲线 
最少知识 

可读性

BehaviourExecutor.Execute(
    new ItemPageNavigationBehaviour(itemUrl),
    new ItemPageBuyBehaviour(),
    new PreviewShoppingCartPageProceedBehaviour(),
    new SignInPageLoginBehaviour(clientLoginInfo),
    new ShippingAddressPageFillShippingBehaviour(clientPurchaseInfo),
    new ShippingAddressPageFillDifferentBillingBehaviour(clientPurchaseInfo),
    new ShippingAddressPageContinueBehaviour(),
    new ShippingPaymentPageContinueBehaviour(),
    new PlaceOrderPageAssertFinalAmountsBehaviour(itemPrice));

可读性评估为非常好(4)。由于行为的名称具有自描述性,您可以猜测其用例。此外,由于您列出了多个行为来定义更大的工作流程,因此步骤的顺序对读者来说是直接可见的。

 基于行为的测试
可维护性5
可读性4
代码复杂度指数 
可用性 
灵活性 
学习曲线 
最少知识 

代码复杂度指数

行为类小巧简单。然而,测试类更复杂,因为您需要初始化整个行为的执行链。

 基于行为的测试
可维护性5
可读性4
代码复杂度指数4
可用性 
灵活性 
学习曲线 
最少知识 

可用性

BehaviourExecutor.Execute(
    new ItemPageNavigationBehaviour(itemUrl),
    new ItemPageBuyBehaviour(),
    new PreviewShoppingCartPageProceedBehaviour(),
    new SignInPageLoginBehaviour(clientLoginInfo),
    new ShippingAddressPageFillShippingBehaviour(clientPurchaseInfo),
    new ShippingAddressPageFillDifferentBillingBehaviour(clientPurchaseInfo),
    new ShippingAddressPageContinueBehaviour(),
    new ShippingPaymentPageContinueBehaviour(),
    new PlaceOrderPageAssertFinalAmountsBehaviour(itemPrice));

测试框架 API 并不复杂。但是,您应该知道要在大工作流程中指定的行为的确切名称。此外,您应该注意它们的正确顺序。有可能弄错某些步骤的顺序。编写工作量更大,因为您需要初始化多个新类。

 基于行为的测试
可维护性5
可读性4
代码复杂度指数4
可用性 
灵活性 
学习曲线 
最少知识 

灵活性

如果您想跳过一些可选的微型工作流程,只需不将其添加到执行器的链中。如果您必须添加一个仅对少量用例有效的自定义微型工作流程,则情况也是如此。您只需要创建行为并将其添加到该特定用例的行为列表中。

 基于行为的测试
可维护性5
可读性4
代码复杂度指数4
可用性4
灵活性5
学习曲线 
最少知识 

学习曲线

对于测试框架 API 的学习曲线来说,属于平均水平(4),因为用户应该知道行为的确切顺序。此外,他/她应该熟悉所有行为的正确名称以及想要调用的确切实现。可能会有多个实现,其中略有不同。

 基于行为的测试
可维护性5
可读性4
代码复杂度指数4
可用性4
灵活性5
学习曲线4
最少知识 

最少知识

您只将必需的参数传递给具体行为。因此,该评分被评为优秀。

 基于行为的测试
可维护性5
可读性4
代码复杂度指数4
可用性4
灵活性5
学习曲线4
最少知识5

在本系列的下一篇文章中,我将使用评估系统来评估基于 SpecFlow 的测试

您可以观看我关于该系统的会议演讲,或下载完整的幻灯片

设计与架构

这篇文章《测试架构设计评估系统 - 基于行为的测试》首次出现在Automate The Planet

所有图片均从 DepositPhotos.com 购买,不可免费下载和使用。
许可协议

© . All rights reserved.