Модульное тестирование позволяет программисту убедиться, что написанный код полностью функционален и работает так, как он должен работать. В отличие от стандартного метода тестирования, когда часть кода запускается разработчиком или тестером, который вручную вводит значения, модульные тесты могут тестировать определенные методы / функции (или любые другие элементы кода), предоставляя тестовые данные в коде.
Один из фундаментальных принципов модульного тестирования — сначала написать тесты, а затем написать самый простой код, который пройдет тест. Обычно я работаю немного по-другому — сначала я пишу простой код, а затем создаю модульные тесты на основе возможных ситуаций. Но это вопрос личного выбора, и если вы работаете наоборот, это не проблема.
Итак, начнем с кода. У меня есть пример тестового приложения и пример класса, содержание которого изложено ниже:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Sandbox{ class Some { public string GetTheValue(string a, int x) { return a + x.ToString(); } public string SampleString(string b, string c) { return b + c; } }}
Здесь у меня есть две функции, обе возвращающие строки, но одна принимает строковые параметры и параметры int, а другая — два строковых параметра. Теперь, чтобы создать модульные тесты для функций, щелкните правой кнопкой мыши объявление функции и выберите «Создать модульные тесты …»
Появится окно, в котором вы можете выбрать классы, методы, функции и свойства из текущего класса (а также из других классов), для которого вы хотите использовать для создания модульных тестов.
На изображении видно, что я выбрал только SampleString в качестве тестируемого объекта. Тем не менее, я также могу выбрать обе функции в классе. После этого в нижней части появляется выпадающее меню «Выходной проект», в котором вы можете выбрать целевой язык программирования для модульных тестов. Поскольку мой основной проект написан на C #, я также создам тестовый проект C #.
При запросе имени введите любое имя, если оно поддерживается IDE. Я назвал свой тестовый проект MyTest.
Теперь вы можете видеть, что к вашему решению добавлен дополнительный проект:
Он имеет только один активный класс с именем SomeTest.cs — это фактический класс тестирования для существующего класса Some.cs в основном проекте. Если вы откроете его, вы увидите автоматически сгенерированный код. После очистки (пока я не концентрируюсь на некоторых деталях), код должен выглядеть примерно так:
using Sandbox;using Microsoft.VisualStudio.TestTools.UnitTesting;using System;namespace MyTest{ [TestClass()] public class SomeTest { [TestMethod()] public void SampleStringTest() { Some target = new Some(); // TODO: Initialize to an appropriate value string b = string.Empty; // TODO: Initialize to an appropriate value string c = string.Empty; // TODO: Initialize to an appropriate value string expected = string.Empty; // TODO: Initialize to an appropriate value string actual; actual = target.SampleString(b, c); Assert.AreEqual(expected, actual); Assert.Inconclusive("Verify the correctness of this test method."); } [TestMethod()] public void GetTheValueTest() { Some target = new Some(); // TODO: Initialize to an appropriate value string a = string.Empty; // TODO: Initialize to an appropriate value int x = 0; // TODO: Initialize to an appropriate value string expected = string.Empty; // TODO: Initialize to an appropriate value string actual; actual = target.GetTheValue(a, x); Assert.AreEqual(expected, actual); Assert.Inconclusive("Verify the correctness of this test method."); } }}
Один из отличительных элементов, который вы заметите первым, если присутствуют атрибуты теста: [TestClass ()] и [TestMethod ()] — они в основном определяют, что тестируется. Вы можете видеть, что тестовый класс является практически идентичной копией класса Some, однако методы структурированы немного иначе. Прежде всего, они не имеют входных параметров и имеют тип void.
Это потому, что тесты используются, чтобы опробовать рабочий механизм блока. Следовательно, проверка не возвращает результаты, а просто выполняет набор действий.
Давайте начнем с SampleStringTest. Внутри этого метода я создаю экземпляр класса Some, а затем создаю две строковые переменные, которые являются параметрами, передаваемыми исходной функции. Я также устанавливаю их значения, так как тест будет выполнен против них. Ожидаемая переменная — это результат, который разработчик ожидает получить при выполнении функции (возвращаемое значение). Фактическая переменная хранит значение, возвращаемое после выполнения.
Существует также метод Assert.AreEqual, который проверяет, совпадает ли ожидаемое значение с возвращаемым. Если это так, то тест проходит. Если это не так, тест не пройден.
По умолчанию значения, указанные для переменных, равны нулю. Я собираюсь изменить это. Для того же метода SampleStringTest я собираюсь использовать этот код:
[TestMethod()]public void SampleStringTest(){ Some target = new Some(); // TODO: Initialize to an appropriate value string b = "Unit"; // TODO: Initialize to an appropriate value string c = " Test"; // TODO: Initialize to an appropriate value string expected = "Unit Test"; // TODO: Initialize to an appropriate value string actual; actual = target.SampleString(b, c); Assert.AreEqual(expected, actual);}
Обратите внимание, что я также удалил вызов метода Assert.Incoclusive. Обычно используется, чтобы показать, что состояние теста не может быть определено. В этом случае я только хочу видеть, терпит ли это неудачу или нет. Я также указал некоторые тестовые значения и ожидаемое значение. Этот тест должен пройти, так как я предоставил правильные тестовые значения и правильное ожидаемое значение.
На панели инструментов «Инструменты тестирования» нажмите кнопку «Выполнить тесты в текущем контексте», когда курсор находится внутри метода SampleStringTest:
Теперь вы должны увидеть диалог Результаты теста внизу:
Как видите, тест пройден. Попробуйте изменить ожидаемое значение, но оставьте переданные значения без изменений. После запуска тест неизбежно провалится:
Та же процедура, которая была применена к методу SampleStringTest, может быть применена и к другому методу тестирования.
В этой статье я показал самые основы модульного тестирования, вершины айсберга, если хотите так его назвать. В этом есть гораздо больше, но это то, что вам нужно знать, чтобы начать. Это гораздо более надежный метод тестирования существующего кода, чем попытка взломать программу с помощью ручного ввода значений. Это, вероятно, не имеет большого значения при работе с конкатенацией строк, но в конечном итоге это очень помогает при работе со сложным сбором и обработкой данных.