测试策略建议——需要记录运行方法的验证结果,并将其用于测试目的

本文关键字:用于 测试 结果 验证 记录 运行 测试策略 方法 | 更新日期: 2023-09-27 17:50:24

我是测试新手,我需要关于最佳测试策略(及其应用)的建议。我的问题是:

我有一个程序,它读取文件并自动提取其结构。我想测试一下这种"智能"提取的方法。最初,我可以使用几个文件来检查该方法是否正在进行正确的提取。然后我想将这些文件和(正确的)提取结果用于测试目的。由于提取结果已得到验证,它们应该(而且必须)用于进一步的测试。

所以,我有这样的东西:对于"this particular file"我期望"this result"

问题:

  1. 很容易获得测试的输入文件。我将把它们存储在一个特定的目录中。结果如何?它们影响存储文件结构的对象的内容。在这种情况下,我可能还需要将这个对象保存在一个文件中。对于序列化,我担心随着对象结构的改变,重用以前保存的对象会变得困难。

  2. 随着越来越多的结果,我可能有数百个文件和结果,测试将花费很多时间。我希望测试时间不会是大问题。

我需要测试,因为我在方法中使用的"提取算法"会经常改变。我不可能为了得到一个完美的提取算法而处理所有的可能性。所以,我的解决方案是建立一个初始算法,它可以在十几个文件中工作,每次我发现算法在特定文件中失败时,我就改变算法,以解决该文件的问题。应该测试此更改,以便之前的文件和结果仍然有效。

对于测试策略有什么建议吗?

测试策略建议——需要记录运行方法的验证结果,并将其用于测试目的

对于测试,您需要一个可以注入输入测试数据的地方和一个可以观察某些行为或输出的地方。

在输入端:文件真的是注入输入测试数据的唯一可能吗?如果是,则说明应用程序没有良好的可测试设计。带有文件的测试很难维护。在输出端:应用程序似乎不提供观察行为或输出的可能性。这是指向一个不可测试的设计。

即使你找到了一种方法来观察我们的输出行为,也只能对所有的提取算法进行端到端测试。这样的端到端测试是脆弱的,并且是维护的噩梦。原因是一个不好的可测试设计。

如果没有良好的可测试设计,您将无法实现良好的测试策略。您将需要更改应用程序的设计。另一方面,您可能会争辩说,您不想在没有进行任何测试的情况下更改设计。这似乎是一个先有鸡还是先有蛋的问题。

如何摆脱这种情况?测试和重构策略的结合可能会有所帮助。在高层,这可能像这样工作:

  1. 构建一些有代表性的端到端测试。因此,即使使用序列化方法。这只是为了验证您的程序是否正常工作比如在你开始重构之前。它们充当迁移测试

  2. 重构程序。给它注射和观察的地方。这样的

  3. 因此,您将拥有可测试的块,您可以将其放入测试

  4. 您重构并将新的接缝放入代码中,以进行更小的测试块,直到有单元测试为止的地方。理想情况下,你将把所有的算法封装到一个类族中,这些类族都是经过单元测试的。

听起来很辛苦?不,实际上这比听起来更难。将应用程序重构为可测试的设计需要大量的经验。幸运的是,有一个人写了一本关于这个的书:Michael Feather的《有效地使用遗留代码》。

如果您真的,真的想要为现有的应用程序实现一个好的测试策略,那么请阅读那本书。如果你想知道下次你能做得更好,那就读那本书。如果您认为单元测试可能是避免不可测试设计的关键,那么现在就开始学习单元测试吧。网上有很多关于单元测试的资源和书籍。

如果我理解了这个问题,您需要将测试的结果持久化,以供以后的检查或额外的测试使用。它经常不愿意在编写测试代码上投入太多时间,但是在这种情况下,我没有看到立即可用的替代方案。

我的建议是尽可能地解耦所涉及的部分:算法,持久层(序列化/反序列化),其产品和验证码。

也可能以后的算法实现可以共享相同的接口,例如:

interface IMyAlgorithm {
  AbstractOutput DoSomething (InputData);
}
class ConcreteOutput : AbstractOutput {
  // Output for version XXX of your algorithm
}
class XXXAlgorithm {
  ConcreteOutput DoSomething (InputData inputData)
    // Version XXX of you alogorithm
  }
}
interface IPersistenceManager {
  Serialize(AbstractOutput output, string filename);
  AbstractOutput Deserialize(string filename)
}
class XXXPersistenceManager : IPersistenceManager {
  // Handle persistence for XXX hierarchy
}
class XXXTestFixture {
  void BuildObjectWithXXXAlgorithm() {
    IMyAlgorithm XXX = new XXXAlgorithm();
    // run XXX here
    AbstractOutput objXXX = XXX.DoSomething(new InputData());
    IPersistenceManager pmXXX = new XXXPersistenceManager();
    pmXXX.Serialize(objXXX);
  }
  void VerifyThatXXXWorkAsExpected() {
    IPersistenceManager pmXXX = new XXXPersistenceManager();
    AbstractOutput objXXX = pmXXX.Deserialize(path);
    // check object here
  }
}

所以当你需要创建一个新的算法,比如YYY,你创建相应的层次结构。无论如何,我不知道细节,这只是伪代码的草稿,放在这里只是为了强调松散耦合的应用程序组件。

您可以尝试使用approvaltests来验证给定的输入文件总是在内存-对象-图中生成相同的文件。

要做到这一点,你需要代码将内存中的对象图转换为它的字符串表示(即覆盖ToString()或具有xml序列化器)

approvaltests验证生成的字符串始终相同。

如果字符串表示改变,您将得到一个差异查看器,并要求您验证更改是否仍然有效。如果更改是正确的,您可以将此结果用于以后的验证。