测试方法应该只测试一个条件吗?

软件测试 自动化测试 测试设计
2022-01-13 17:58:06

在编写自动化测试时,我遇到了在一种方法中包含多个验证点的情况,但后来我也读到/听说过一个测试应该只进行一个验证。您遵循哪种方法,为什么?

nb 我有我的指针,可以用一种方法进行多次验证,一旦我得到满意的答案,我会详细说明它们。看起来我提出了一个更主观/争论的问题。

4个回答

我将多个验证合并到一个测试中,但只在测试执行的一个时间点允许它们。测试工具从失败的验证中优雅地恢复(验证不应该更改状态 IMO;如果收集数据更改状态,则收集数据作为测试的一部分或使该验证成为另一个测试)并继续执行其他验证。

为什么要进行多次验证?

  1. 如果导致失败的 bug 是可重复且一致的,那么它会在下一次再次重复,并导致与以前相同的验证失败。如果每次结果都相同,为什么还要浪费设置时间?
  2. 如果导致失败的错误是不可重复和一致的,我想尽可能多地收集有关该特定失败的信息——最好通过多次验证来完成。

为什么他们只在测试中的某一时刻出现?

  1. 设置失败与实际测试失败不同,我的测试工具以不同方式处理它们。我也可以轻松地以不同的方式报告它们,并且这些信息对业务决策很有用。
  2. 如果测试 B 依赖于测试 A 并且测试 A 失败,我无法解决测试 A 的错误以修复测试 B,因为这会改变测试 A。如果 A 和 B 是单独的测试,那么我可以重写测试设置B 在不影响测试 A 的情况下解决测试 A 中的错误。例如,如果 A 正在发布评论,而 B 正在查看来自另一个帐户的已发布评论,并且发布评论失败,因为评论“提交”按钮的 JavaScript 已损坏,我仍然可以通过直接在设置中更新数据库来测试 B,然后验证是否正确提交了评论,另一个帐户将能够查看它。

编辑添加: 我刚刚意识到臭名昭著的“Given-When-Then”格式遵循相同的规则。您有一个测试(“When”部分),在“when”完成后,您可以使用“and”关键字验证多个“then”语句。所以有一种方法可以解决这个问题。

我个人喜欢原子测试,通常设计为只测试一两件事,大多数验证在测试用例本身中被显式调用。这样您就可以轻松地在顶层查看正在验证的内容,例如(来自 parkcalc)。

    [TestMethod]
    public void InvalidTextAsExitDate()
    {
        Parking.Calculate(ParkingType.LongTermSurfaceParking, "12:00", "AM", "today", "12:00", "AM", "INVALID");
        Verify.SpecificErrorIsShown(ErrorMessages.EnterCorrectDate);
    }

    [TestMethod]
    public void OnlySpecifyEntryDate()
    {
        Parking.Calculate(ParkingType.LongTermSurfaceParking, "12:00", "AM", "today", "12:00", "AM", "");
        Verify.VerifyResult(ParkingType.LongTermSurfaceParking, "12:00", "AM", "today", "12:00", "AM", "");
    }

每当我将验证推到较低级别时,我总是在想,“这到底是在验证什么。”,例如

    [TestMethod]
    public void OnlySpecifyExitDate()
    {
        Parking.CalculateAndVerify(ParkingType.LongTermSurfaceParking, "12:00", "AM", "", "12:00", "AM", "today");
    }

然后下一个级别是

    public static void CalculateAndVerify(ParkingType parkingType, string inTime, string inAMPM, string inDate, string outTime, string outAMPM, string outDate)
    {
        Calculate(parkingType, inTime, inAMPM, inDate, outTime, outAMPM, outDate);
        Verification.Verify.VerifyResult(parkingType, inTime, inAMPM, inDate, outTime, outAMPM, outDate);
    }

我的框架的完整工作示例解决方案可在https://github.com/teknologika/stax

在一个测试中组合太多东西的另一个缺点是,失败可能会阻止其他验证的发生。

假设您结合了三个验证,而第二个验证失败。你的自动化会停止吗?还是继续三连?三是有多重要?如果您可以在没有经过验证的情况下生活,那么合并将节省时间。但是,如果三个被验证是重中之重,我会把它自己放在一边,慢慢来。

对于单元测试,我非常喜欢每次测试测试一件事。原因是这样的:当测试失败时,我希望测试尽快将我指向损坏的代码。

如果一个测试测试多个东西,那么测试的名称不足以指向损坏的代码。我必须寻找其他信息,例如堆栈跟踪,它可以引导我找到一行测试代码。然后我必须查看测试代码行,看看它在做什么,以及在什么上下文中。现在,这不是我遇到过的最可怕的问题,但是...

如果测试测试一件事,那么失败测试的名称通常足以为我指明正确的方向。不总是,但经常。

出于不同的原因,我也更喜欢让每个验收测试都成为一件事。但在这里,我的理由主要是清晰。我希望每个验收测试都能清晰地描述它正在测试的功能或责任。我想看看为什么这个测试很重要。测试做的事情越多,就越难理解测试的重点。

我更有可能放松对验收测试的偏好,尤其是通过 GUI 或浏览器进行测试时。启动和拆卸有时需要很长时间。如果我在每个测试中做更多的事情,那么我执行的那些长时间运行的设置和拆卸就会更少,因此套件运行时间会更少。另一方面,每个测试都需要更长的时间来运行,如果该测试嵌入到更大的“创建一个 frobozz,编辑它,保存它,删除它”测试中,就不可能只测试“创建一个新的 frobozz”的东西.