3

我需要一些关于我的软件测试的指导。

我把事情复杂化了,但我太专注于看我做错了什么,或者另一种做事方式。

我有几个使用相同私有方法的公共方法。

私有方法本身:

  • 必须为其特定角色处理许多场景
  • 与同一实例中的字段/属性/方法密切合作

假设私有方法需要 5 次测试才能覆盖所有场景,并被 6 个公共方法使用。

问题

  • 那么我至少需要5x6测试吗?

  • 如何为每个公共方法重用私有方法的测试?

  • 有没有关于重构重复测试的示例/文章?

例子

启动()

- if_file_exists_load_entries           ()
- if_file_missing_load_last             ()
- if_no_files_create_new_entries        ()
- if_exception_clear_entries_and_log    ()
- loaded_entries_init_called            ()
- Other tests

OnUserLoadCustom()

- if_file_exists_load_entries           _AND_STORE_AS_LAST()
- if_file_missing_load_last             _AND_STORE_AS_LAST_AND_WARNING_MESSAGE()
- if_no_files_create_new_entries        _AND_WARNING_MESSAGE()
- if_exception_clear_entries_and_log    _AND_ERROR_MESSAGE()
- loaded_entries_init_called            _AND_SUCCESS_MESSAGE()
- Other tests

OnRecover()

- if_file_exists_load_entries           _AND_INFO_MESSAGE()
- if_file_missing_load_last             _AND_INFO_MESSAGE()
- if_no_files_create_new_entries        _AND_INFO_MESSAGE()
- if_exception_clear_entries_and_log    _AND_ERROR_MESSAGE_AND_SHUTDOWN()
- loaded_entries_init_called            _AND_SUCCESS_MESSAGE()
- Other tests

我正在考虑使用策略模式封装私有方法,因此我可以单独测试它(和公共方法)。

但是,我觉得使用其中一个不合适,因为:

  • 我不打算在运行时有可互换的行为
  • 为了更容易测试而使用模式似乎是错误的

更新#1

我的问题与测试私有方法行为的公共接口有关。但我最终得到了很多重复的测试方法(见我上面的例子)。

对于策略模式,我认为我需要的只是:

  • 测试策略中的所有路径(本质上是测试私有方法)
  • 验证所有公共方法都调用了策略(可以在这里轻松地使用模拟对象,并验证它是否被调用)

但就像我提到的那样,我认为我不应该仅仅为了更容易测试而引入一种模式。除非我真的必须这样做,否则我会推迟这种方法。


更新#2

减少重复的第一次尝试:

  • 私有方法测试分组到自己的类(Behaviour1Test)

    • GetTestCases() 返回与此行为相关的测试用例列表
  • 所有需要这个测试的公共方法都实现了暴露的接口

    • 安排()
    • 行为()
    • 断言()

例如:

// Public method tests
[TestFixture]
public class PublicMethodTests: IBehaviour1Test
{
    // Behaviour 1
    Behaviour1Test _behaviour1;
    IEnumerable<TestCaseData> Behaviour1TestCases{ get { return _behaviour1.GetTestCases(); } }
    [Test]
    [TestCaseSource("Behaviour1TestCases")]
    public void RunBehaviour1Test(Action<IBehaviour1Test> runTestCase)
    {
        runTestCase(this);
    }

    // ==============================
    // Behaviour 1 Arrange/act/assert
    void IBehaviour1Test.Arrange(){}
    void IBehaviour1Test.Assert(object result){}
    object IBehaviour1Test.Act()
    {
        return _model.PublicMethod();        
    }

    // Other tests
}

// Implement this in order to run Behaviour1 test cases
interface IBehaviour1Test
{
    void Arrange(); 
    object Act();
    void Assert(object retValue);
}

// Collection of tests for behaviour 1
public class Behaviour1Test
{
    // Generate test cases
    IEnumerable<TestCaseData>() GetTestCases()
    {
        yield return new TestCaseData((Action<IBehaviour1Test>)Test_1);
        yield return new TestCaseData((Action<IBehaviour1Test>)Test_2);
        yield return new TestCaseData((Action<IBehaviour1Test>)Test_3);
    }

    void Test_1(IBehaviour1Test impl)
    {
        // Arrange
        impl.Arrange(); // public method's arrange
        Test1Setup(); // Arrange for this test

        // Act
        var result = impl.Act();

        // Assert
        Test1Assert(result); // Assert for this test
        impl.Assert(result); // Assert on public method

    }

    void Test_2(IBehaviour1Test impl){}
    void Test_3(IBehaviour1Test impl){}
}

这样,如果我需要为私有方法的行为添加一个新的测试用例,我只需要在 BehaviourTest 中添加一次,所有包含它的公共方法测试都会更新。

在此处输入图像描述

4

3 回答 3

2

您应该在测试中应用与在应用程序代码中相同的理念。如果可以将通用功能提取到辅助方法或类中,那么您应该这样做。它将为您节省代码重复,并在私有方法发生更改时帮助您稍后重构。

我想你有很多通用的设置、拆卸、断言和验证代码,可以推广。

于 2012-10-02T00:33:46.180 回答
1

从某种意义上说,您不会测试私有方法。您彻底测试使用私有方法的方法,并且一切都检查出来,私有方法“有效”。

如果你真的想要安心,你可以使用反射来执行私有方法,这样你就可以单独测试它。

关于测试重构,您当然应该有设置和拆卸例程来处理这些相应的功能。我不会在测试中进入策略模式,只需在测试类中创建非测试方法,这些方法具有多个测试所需的功能块并适当地使用它们。例如,如果您的私有方法可以影响 5 个字段,并且您需要多次测试这 5 个字段,我会创建一个类似的方法

private void verifyField(expected1, extpected2, ....){
     equals(actual1, expected1, 'expected1 correct);
     ....
}

并在适当的地方使用它。

于 2012-09-28T12:11:27.210 回答
0

您需要将私有方法提取到辅助类中。然后分别测试它的功能并在其他测试中模拟它。私有方法中的功能与您尝试在其他方法中测试的内容无关——它只提供输入。大多数私有方法通常只是等待释放的辅助方法。

于 2012-10-03T13:25:57.817 回答