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

C# 测试策略建议-需要记录运行方法的验证结果,并将其用于测试目的,c#,testing,C#,Testing,我是测试新手,我需要一个关于最佳测试策略(及其应用)的建议。 我的问题是: 我有一个程序,可以读取文件并自动提取其结构。我想测试这种“智能”提取的方法。最初,我可以使用一些文件来检查该方法是否进行了正确的提取。然后我想使用这些文件和(正确的)提取结果进行测试。由于提取结果已得到验证,因此应(且必须)将其用于进一步试验 所以,我有这样的想法:对于“这个特定文件”,我期望“这个结果” 问题是: 很容易获得测试的输入文件。我将把它们存储在一个特定的目录中。结果如何?它们影响存储文件结构的对象的内容。在

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

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

所以,我有这样的想法:对于“这个特定文件”,我期望“这个结果”

问题是:

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

  • 随着越来越多的结果,我可能有数百个文件和结果,测试将花费大量时间。我预计测试时间不会是一个大问题

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


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

    如果我了解问题所在,您需要保留测试结果以供以后检查或附加测试。 它通常不愿意在编写测试代码上投入太多时间,但在这种情况下,我看不到立即可用的替代方案

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

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

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

    您可以尝试使用来验证这一点 给定的输入文件总是生成相同的内存对象图

    为此,您需要将内存中的对象图转换为其字符串表示形式的代码(即重写ToString()或使用xml序列化程序)

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


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

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

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

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

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

    如何摆脱这种局面?测试和重构策略的组合可能会有所帮助。在高层,这可能是这样的:

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

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

  • 因此,您将拥有可测试的块,您可以将其放入 测试线束

  • 您可以重构代码并在代码中添加新的接缝,以测试更小的代码 块,直到你达到了你有单元测试的程度 地点。理想情况下,您将把所有算法封装到一系列类中,这些类都经过单元测试

  • 听起来很难做?不,事实上这比听起来更难。将应用程序重构为可测试设计需要大量经验。幸运的是,有一个人写了一本关于这个的书:


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

    你的输出是什么类型的?它是一个
    c#
    对象吗?是的,它是一个c#对象。从某种意义上说,它不是一个简单的对象,它直接和间接地涉及来自几个不同类的对象,并且可能很难序列化。