Является ли хорошей идеей добавить параметр TestSettings в метод, чтобы сделать его (единичный или интеграционный) тестируемым? - PullRequest
1 голос
/ 03 ноября 2010

Является ли хорошей практикой введение класса TestSettings, чтобы обеспечить гибкие возможности тестирования метода, в котором много процессов?

Возможно, это не хороший пример, но может быть простым: предположим, у меня есть этометод и я хочу проверить его подпроцессы:

public void TheBigMethod(myMethodParameters parameter)
{

  if(parameter.Condition1)
   {
     MethodForCondition1("BigMac"); 
   }

  if(parameter.Condition2)
   {
     MethodForCondition2("MilkShake"); 
   }

  if(parameter.Condition3)
   {
     MethodForCondition3("Coke"); 
   }

  SomeCommonMethod1('A');
  SomeCommonMethod2('B');
  SomeCommonMethod3('C');
}

И представьте, что у меня есть модульные тесты для всех

  • void MethodForCondition1 (string s)
  • void MethodForCondition2 (string s)
  • void MethodForCondition3 (string s)
  • void SomeCommonMethod1 (char c)
  • void SomeCommonMethod2 (char c)
  • void SomeCommonMethod3(char c)

А теперь я хочу протестировать сам TheBigMethod, представив такие методы тестирования с необходимыми в них утверждениями:

  • TheBigMethod_MethodForCondition1_TestCaseX_DoesGood
  • TheBigMethod_MethodForCondition3_TestCaseZ_DoesGood
  • TheBigMethod_SomeCommonMethod1_TestCaseU_DoesGood
  • TheBigMethod_SomeCommonMethod2_TestCaseP_DoesGood
  • TheBigMethod_SomeCommonMethod3_TestCaseQ_DoesGood * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * '' он ''.мои интеграционные тесты выше.
    public void TheBigMethod(myMethodParameters parameter, TestSettings setting)
    {
    
      if(parameter.Condition1)
       {
         MethodForCondition1("BigMac"); 
    
         if(setting.ExitAfter_MethodForCondition1)
            return;
    
       }
    
      if(parameter.Condition2)
       {
         MethodForCondition2("MilkShake"); 
    
         if(setting.ExitAfter_MethodForCondition2)
            return;
    
       }
    
      if(parameter.Condition3)
       {
         MethodForCondition3("Coke"); 
    
         if(setting.ExitAfter_MethodForCondition3)
            return;
    
       }
    
      SomeCommonMethod1('A');
      if(setting.ExitAfter_SomeCommonMethod1)
           return;
    
      SomeCommonMethod2('B');
      if(setting.ExitAfter_SomeCommonMethod2)
           return;
    
      SomeCommonMethod3('C');
      if(setting.ExitAfter_SomeCommonMethod3)
           return;
    }
    

    Несмотря на то, что он выглядит так, он делает то, что мне нужно, чтобы ввести параметр TestSetting, который может сделать код менее читабельным и не очень приятным, если мне объединить логику тестирования и основные функции.

    Можете ли вы посоветовать лучший дизайн для таких случаев, чтобы он мог заменить идею параметра TestSetting?

    спасибо

Ответы [ 2 ]

2 голосов
/ 04 ноября 2010

Немного опоздал к игре, но я согласен, что смешивание тестового и производственного кода - это большой запах кода, которого следует избегать. Большие методы в унаследованном коде обеспечивают всевозможные проблемы. Я очень рекомендую прочитать «1001 * Эффективная работа Майкла Фезера с устаревшим кодом» . Все дело в том, чтобы справиться с множеством проблем, встречающихся в унаследованном коде, и как с ними справиться.

2 голосов
/ 03 ноября 2010

(IMO) было бы очень плохо добавить этот TestSetting.Альтернативой может быть добавление интерфейса (или набора интерфейсов) для MethodForCondition X и SomeCommonMethod X .Проверяйте каждое из MethodForCondition X & SomeCommonMethod X изолированно и передавайте заглушку для TheBigMethod, которая проверяет, что MethodForCondition X вызывается со значением Z.

Редактировать : Вы также можете сделать методы виртуальными, если не хотите использовать интерфейс.

...