2016-11-18 5 views
2

C# Новичок здесь.Конфигурация тестового корпуса для функции Max()

Я понимаю, что тестовые случаи должны быть:

  • Простые и прозрачные
  • имеют минимальные повторы
  • Обеспечение 100% покрытия кода

Я также понимаю основы Boundary-стоимостного анализа и разделением эквивалентности, но с приведенной ниже функцией, какими будут основные тестовые примеры?

static public int Max(int a, int b, int c) 
    { // Lines of code: 8, Maintainability Index: 70, Cyclomatic Complexity: 4, Class Coupling: 0 
     if (a > b) 
      if (a > c) 
       return a; 
      else 
       return c; 
     else 
      if (b > c) 
       return b; 
      else 
       return c; 
    } 

Это то, что я до сих пор ..

using Microsoft.VisualStudio.TestTools.UnitTesting; 
    using ConsoleApplication10; 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Threading.Tasks; 

    namespace ConsoleApplication10.Tests 
    { 
     [TestClass()] 
     public class ProgramTests 
     { 
      [TestMethod()] 
      public void MaxTestNulls(int a, int b, int c) 
      { 
       Assert.IsNotNull(a, "The first parameter must be present."); 
       Assert.IsNotNull(b, "The second parameter must be present."); 
       Assert.IsNotNull(c, "The third parameter must be present."); 
      } 
      [TestMethod()] 
      public void MaxTestTypes(int a, int b, int c) 
      { 
       Assert.IsInstanceOfType(a, typeof(int)); 
       Assert.IsInstanceOfType(b, typeof(int)); 
       Assert.IsInstanceOfType(c, typeof(int)); 
      } 
      [TestMethod()] 
      public void MaxTestBasics(int a, int b, int c) 
      { 
       if (a > int.MaxValue || b > int.MaxValue || c > int.MaxValue) 
       { 
        Assert.Fail(); 
       } 

       if (a < int.MinValue || b < int.MinValue || c < int.MinValue) 
       { 
        Assert.Fail(); 
       } 
      } 
     } 
    } 

Am Я полностью покинуть базу здесь? Мой учитель не выпучится и не даст мне никаких намеков. Какие другие тестовые примеры я мог бы использовать, это было бы полезно?

ответ

2

Одна жизнеспособная стратегия тестирования называется охватом филиалов. Там вы пытаетесь написать модульные тесты, которые охватывают каждую ветвь выполнения в тестируемой системе.

В вашем случае, различные ветви исполнения являются return инструкции: return a, return c, return b и снова return c на дне.

Вы можете покрыть всю функцию с этими прецедентами (значения для а, Ь и с, соответственно):

4, 2, 3 
4, 2, 5 
4, 2, 4 <-- boundary condition 
2, 4, 3 
2, 2, 3 <-- boundary condition 
2, 4, 5 
2, 4, 4 <-- boundary condition 

Есть ровно четыре случая испытания, которые гарантируя, что все ветви покрыты. Дополнительные три случая заключаются в том, чтобы покрыть граничные условия, которые по-прежнему оказываются в определенных отраслях.

Ниже приведена реализация этих тестовых примеров в xUnit. Я выбрал XUnit, поскольку он поддерживает несколько тестов для одного метода испытания пути использования атрибута InlineData:

[Theory] 
[InlineData(4, 2, 3, 4)] 
[InlineData(4, 2, 5, 5)] 
[InlineData(4, 2, 4, 4)] 
[InlineData(2, 4, 3, 4)] 
[InlineData(2, 2, 3, 3)] 
[InlineData(2, 4, 5, 5)] 
[InlineData(2, 4, 4, 4)] 
public void Max_ReturnsExpectedValue(int a, int b, int c, int expectedMax) 
{ 
    int actualMax = Program.Max(a, b, c); 
    Assert.Equal(expectedMax, actualMax); 
} 

Просто для записи, все семь тестов передают для реализации выше.

Относительно примечания, такой тип тестирования называется тестированием с использованием белого ящика. У вас есть доступ к конкретной реализации, а затем вы пишите тесты для этой реализации. Если вы хотите реализовать тестирование «черного ящика», ваши тестовые примеры будут зависеть только от ожиданий от функции. Например, это могут быть законные тестовые случаи для черных испытаний коробчатых:

1, 1, 1 -> 1 
1, 1, 2 -> 2 
1, 2, 1 -> 2 
1, 2, 2 -> 2 
1, 2, 3 -> 3 
1, 3, 1 -> 3 
1, 3, 2 -> 3 
1, 3, 3 -> 3 
2, 1, 1 -> 2 
... 

Проблема здесь состоит в том, что мы не знаем, какие граничные условия актуальны и поэтому мы должны добавить довольно много из них, чтобы покрыть все варианты. Если вы продолжаете идти в том же направлении, общее количество тестов будет 3^3 = 27.

+0

Это очень полезно, спасибо. Еще один вопрос: как мне реализовать это в своих модульных тестах? Всякий раз, когда я пытаюсь вызвать Max() внутри моего TestMethods(), он дает ошибку. – dotKn0ck

+0

Наверное, я запутался в реализации. – dotKn0ck

+0

@ dotKn0ck См. Выше описанную методику тестирования. –

0

первое очевидное дополнение похоже на itsme86 говорит, что вы должны проверить, если какой-либо из трех входов равен.

Во-вторых, вы должны проверить зависимость, то есть значения входов могут потенциально быть выходными функциями, которые изменяются для каждой оценки, поэтому обязательно возьмите один экземпляр ввода в вашем тестовом классе (т.е. оцените один раз) и продолжать свои тесты на этом локальном экземпляре и не переоценивать вход

Я не знаю много о C#, но позвольте мне показать вам общий пример

public static TestFunction (int A, int B, int C) 
{ 
// Your test methods 
} 

, если это вызывается как это

boolean Result = TestFunction((int)Math.sin(System.currentTimeMillis()),(int)Math.sin(System.currentTimeMillis()),(int)Math.sin(System.currentTimeMillis())); 

каждый раз, когда в вашей функции вы доступ A, B или C их значение будет переоценено и может можно свести на нет результата предыдущих тестов

Я хотел бы добавить дополнительное испытание, как X = A, Y = A, XY = 0, чтобы убедиться, что A не изменится при переоценке, возможно, добавляет задержку времени, зависящую от времени, и программа выполняется слишком быстро, чтобы это отразилось (вам нужно нано-второе разрешение, чтобы отразить в непрерывном выполнении кода, который мал и прост)

 Смежные вопросы

  • Нет связанных вопросов^_^