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

时间:2013-01-03 00:46:25

标签: c# testing

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

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

所以,我有类似的内容: for“this specific file”我希望“这个结果”。

问题:

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

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

  3. 我需要测试,因为我在方法中使用的“提取算法”会经常更改。我无法应对所有可能性以获得完美的提取算法。因此,我的解决方案是构建一个初始算法,该算法可以在十几个文件中运行,每次我发现特定文件的算法失败时,我都会更改算法以解决该文件的问题。应该测试此更改,以便先前的文件和结果仍然有效。

    有关测试策略的任何建议吗?

3 个答案:

答案 0 :(得分:1)

对于测试,您需要某处可以注入输入测试数据的位置以及可以观察某些行为或输出的位置。

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

即使您找到了观察行为输出的方法,也只会对所有提取算法进行端到端测试。这种端到端测试很脆弱,也是维护的噩梦。原因是一个不太好的可测试设计。

如果没有良好的可测试设计,您将无法实施良好的测试策略。您需要更改应用程序的设计。另一方面,您可能会争辩说,如果没有任何测试,您不希望更改设计。这似乎是鸡与蛋的问题。

如何摆脱这种情况?测试和重构策略的组合可能会有所帮助。在高级别上,这可能是这样的:

  1. 构建一些有代表性的端到端测试。因此即使使用 序列化技巧。这只是为了验证您的程序是否有效 就像你开始重构之前一样。它们充当迁移测试

  2. 重构你的程序。给它注射和观察的地方。这样 地方被称为接缝

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

  4. 您重构并将新的接缝放入代码中,以测试较小的 块,直到你到达单元测试为止 地点。理想情况下,您将所有算法封装到一系列类中,这些类都经过单元测试。

  5. 听起来很辛苦?不,实际上它比听起来更难。将应用程序重构为可测试设计需要大量经验。幸运的是,有一个人写了一本书:Michael Feather’s 'Working Effectively with Legacy Code'

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

答案 1 :(得分:0)

如果我理解了这个问题,您需要保留测试结果,以便以后检查或进行其他测试。 它通常不愿意花太多时间编写测试代码,但在这种情况下我看不到立即可用的替代方案。

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

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

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)时,您将创建相应的层次结构。无论如何,我不知道细节,这只是一个伪代码草案,放在这里只是为了强调松散耦合应用程序组件。

答案 2 :(得分:0)

您可以尝试使用approvaltests来验证 给定的输入文件总是在memory-object-graph中生成相同的内容。

要做到这一点,您需要将内存对象图转换为字符串表示形式的代码(即覆盖ToString()或具有xml-serializer)

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

如果字符串表示变化,您将获得差异查看器,并要求您验证更改是否仍然正常。如果更改正常,您将获取此结果以供日后验证。