更好的实施"步数"

时间:2015-01-26 13:12:34

标签: c#

我正在编写将执行一系列测试步骤的代码,这些测试步骤将与测试用例中手动捕获的测试步骤一致,这是一个示例:

enter image description here

上面的屏幕截图显示了示例测试用例的3个步骤(使用Microsoft Test Manager查看)。

请记住,这是一个原始的例子,简化了这个问题,实际上有50个测试步骤和更复杂的场景并不罕见,我也省略了清理以及下面函数中的输入代码。

现在运行它的代码看起来像这样:(注意try / catch机制,允许测试在特定步骤失败):

[TestMethod]
       public void LinksPageOpensFromClick()
       {
          int step = 0;

          try
          {
             step++;
             // Code to Open the page
          }
          catch (Exception ex )
          {
             Assert.Fail(AppManager.RaiseError(step, "Open the page", ex));
          }

          try
          {
              step++;
             // Code to Click links button
          }
          catch (Exception ex)
          {
             Assert.Fail(AppManager.RaiseError(step, "Click links button", ex));
          }

          try
          {
             step++;
             // Code to Assert links page opened 
          }
          catch (Exception ex)
          {
             Assert.Fail(AppManager.RaiseError(step, "Assert links page opened ", ex));
          }
       }

首先观察的是,我过去只是硬编码这样的步骤值:

Assert.Fail(AppManager.RaiseError(3, "Assert links page opened ", ex));

但这意味着如果测试稍后更改,并且添加或重新排序测试步骤,则意味着手动更改大量步骤。

将步骤作为递增变量也不是理想的,首先它不是很优雅,如果你忘记增加步数,它就太容易出错了。此外,您无法对代码进行模式扫描,看看您在不添加其他评论的情况下执行了哪些步骤。

我真正想要的是这样的解决方案:

[StepDesc="Assert links page opened"]
Step
{
   // Code to exec
}
Error (Exception ex)
{
   Assert.Fail(AppManager.RaiseError(Step.Count, Step.Desc, ex));
}

如果失败了,可以更简洁地增加步数或使其更加动态而无需手动递增。

提前致谢。

编辑:如果C#无法解决这个问题,也许我可以将所有面向前面的测试用例放在另一个可能不是C#但符合MSIL的项目中?

2 个答案:

答案 0 :(得分:4)

这显然需要循环,例如:

class Step 
{
    public string Name { get; set; }
    public Action Action { get; set; }
}

var steps = new []
{
    new Step() { Name = "Open the page", Action = OpenThePageStep },
    new Step() { Name = "Click links button", Action = ClickLinksBtnStep },
    ...
};

...

var id = 0; // or the Step class itself should have an id?
foreach (var step in steps)
{
    try
    {
        id++;
        step.Action();
    }
    catch (Exception ex)
    {
        Assert.Fail(AppManager.RaiseError(id, step.Name, ex));
    }
}

答案 1 :(得分:2)

如果步骤是手动实现的(并且不是例如从正式描述中自动生成,在这种情况下定义Step类的Groo's solution确实更好),这可能是我如何做到的,因为它似乎是最简单的方法,至少如果每一步的代码都很简单,我也发现它更具可读性:

public class Stepper
{
    private int StepNumber { get; set; }

    public void Step(string description, Action code)
    {
        StepNumber++;
        try
        {
            code();
        }
        catch (Exception ex)
        {
            Assert.Fail(AppManager.RaiseError(StepNumber, description, ex));
        }
    }
}

然后您的测试代码如下所示:

var stepper = new Stepper();

stepper.Step("Open the page", () => { /* code to open the page */ });
stepper.Step("Click links button", () => { /* code to click links button */ });

// etc.

对您而言可能或可能不感兴趣的一件事是,您可以相当轻松地实现创建嵌套步骤的方法,例如:

之类的东西
var stepper = new Stepper();

stepper.Step("Foo the bar", () => { /* ... */ });

using (var substep = stepper.SubStep("baz all the quuxs"))
{
    substep.Step("baz the first quux", () => { /* ... */ });
    substep.Step("baz the second quux", () => { /* ... */ });
}

stepper.Step("cleanup", () => { /* ... */ });