19
Темы лекции: Unit-тестирование. Практическое задание: Unit-тестирование. Тренер: Игорь Шкулипа, к.т.н. Платформа .Net и язык программирования C#. Занятие 17

C# Desktop. Занятие 17

Embed Size (px)

Citation preview

Page 1: C# Desktop. Занятие 17

Темы лекции: Unit-тестирование.

Практическое задание: Unit-тестирование.

Тренер: Игорь Шкулипа, к.т.н.

Платформа .Net и язык программирования C#.

Занятие 17

Page 2: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 2

Модульное тестирование

Unit testing (юнит тестирование или модульное тестирование) —заключается в изолированной проверке каждого отдельного элементапутем запуска тестов в искусственной среде.

Unit (Элемент) — наименьший компонент, который можноскомпилировать.

Драйверы — модули тестов, которые запускают тестируемый элемент.

Заглушки — заменяют недостающие компоненты, которые вызываютсяэлементом и выполняют следующие действия:

• возвращаются к элементу, не выполняя никаких других действий;• отображают трассировочное сообщение и иногда предлагают

тестировщику продолжить тестирование;• возвращают постоянное значение или предлагают тестеру самому

ввести возвращаемое значение;• осуществляют упрощенную реализацию недостающей

компоненты;• имитируют исключительные или аварийные условия.

Page 3: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 3

Подходы к unit-тестированию

White-box testing. Для конструирования тестов используютсявнутренняя структура кода и управляющая логика. При этом существуетвероятность, что код будет проверяться так, как он был написан, а это негарантирует корректность логики.

Black-box testing. Для конструирования тестов используются требованияи спецификации ПО.

Недостатки:• таким способом невозможно найти взаимоуничтожающихся

ошибок,• некоторые ошибки возникают достаточно редко (ошибки работы с

памятью) и потому их трудно найти и воспроизвести

Page 4: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 4

Стратегия модульного тестирования

Модульное тестирование является одной из ключевых практикметодологии экстремального программирования:

• Написание тестов помогает войти в рабочий ритм

• Придает уверенность в работоспособности кода.

• Дает запас прочности при дальнейшей интеграции или измененияхкода.

Модульное тестирование оправдано, если оно:

• Снижает время на отладку

• Дает возможность поиска ошибок с меньшими затратами, нежелипри других подходах

• Дает возможность дешевого поиска ошибок при изменениях кода вдальнейшем

Page 5: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 5

Цель модульного тестирования

Получение работоспособного кода с наименьшими затратами. И его применениеоправдано тогда и только тогда, когда оно дает больший эффект, нежели другиеметоды.

Отсюда следует несколько выводов:

• Нет смысла писать тесты на весь код. Некоторые ошибки проще найтина более поздних стадиях. Так, например, для ООП данное правило можетзвучать так: нет смысла писать тесты на класс, который используетсятолько одним классом. Эффективней написать тесты на вызывающий класси создать тесты тестирующие все участки кода.

• Писать тесты для кода потенциально подверженного изменениямболее выгодно, чем для кода, изменение которого не предполагается.Сложная логика меняется чаще, чем простая. Следовательно, в первуюочередь имеет смысл писать модульные тесты на сложную логику. А напростую логику писать позднее или вообще тестировать другими методами.

• Для того чтобы как можно реже изменять тесты следует хорошопланировать интерфейсы. То же самое можно сказать и применительно кнаписанию исходного кода. Действительно, создание хорошей архитектурычасто определяет дальнейший ход проекта. И есть оптимум, на каком этапеархитектура «достаточно хороша».

Page 6: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 6

Планирование тестов

• Код с не оттестированными участками не может быть опубликован

• Тесты должны базироваться на спецификации

• На каждое требование должен быть, как минимум, один тест. Неважно,ручной или автоматический

• Простой тест нужен т.к. несмотря на малую вероятность нахожденияошибки, цена пропущенной ошибки чрезмерно высока

• Наиболее эффективный способ создания тестового набора —совместное использование методов черного и белого ящиков.

Page 7: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 7

TDD

TDD (Test-Driven Development) - это методика разработки, позволяющаяоптимизировать использование модульных тестов. Стоит подчеркнуть,что речь идет именно об оптимальном, а не максимальномприменении. Задача, которую преследует TDD, - достижение балансамежду усилиями и результатом.

С практической точки зрения, основой TDD является цикл«red/green/refactor»:

• в первой фазе программист пишет тест,• во второй - код, необходимый для того, чтобы тест работал,• в третьей, при необходимости, производится рефакторинг.

В соответствии с принципом "Test First", следует писать только такойкод, который абсолютно необходим, чтобы тесты выполнялисьуспешно.

Page 8: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 8

Пример. Создание теста

Page 9: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 9

Пример. Создание теста

Page 10: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 10

Пример. Создание теста

Page 11: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 11

Класс-тест

using System;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject1

{

[TestClass]

public class UnitTest1

{

[TestMethod, ExpectedException(typeof(ArgumentException))]

public void TestMethod1()

{

TDDExample.FactorialClass.Factorial(-1);

}

}

}

Page 12: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 12

Тестируемый класс

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Numerics;

namespace TDDExample

{

public class FactorialClass

{

public static BigInteger Factorial(int number)

{

if (number < 0) throw new

ArgumentException("Argument is Less than Zero.");

if (number == 0) return 1;

else return Factorial(number - 1) * number;

}

}

}

Page 13: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 13

Запуск теста

Page 14: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 14

Тест с другими данными

14

using System;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject1

{

[TestClass]

public class UnitTest1 {

[TestMethod, ExpectedException(typeof(ArgumentException))]

public void TestMethod1()

{

TDDExample.FactorialClass.Factorial(10);

}

}

}

Page 15: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 15

Класс Assert

Проверяет условия, использующие утверждения "истина/ложь", в процессемодульных тестов.

Пространство имен: Microsoft.VisualStudio.TestTools.UnitTesting

Методы:

• AreEqual, AreEqual<T> / AreNotEqual, AreNotEqual<T> + 17 перегрузок -проверяет два указанных объекта на равенство/неравенство. Утверждение невыполняется, если объекты не равны.

• AreSame / AreNotSame + 2 перегрузки - проверяет, ссылаются ли двеуказанные объектные переменные на один и тот же объект / на разные объекты.

• Equals - определяет равенство двух объектов.

• Fail - отменяет выполнение утверждения без проверки каких-либо условий.

• Inconclusive - указывает, что утверждение не может быть проверено.

• IsFalse / IsTrue - проверяет, имеет ли указанное условие значение false/true.

• IsInstanceOfType / IsNotInstanceOfType - проверяет, является / не являетсяли указанный объект экземпляром заданного типа.

• IsNull / IsNotNull - проверяет, имеет / не имеет ли указанный объект значениеnull

• ReplaceNullChars - заменяет в строке символы null ('\0') на "\\0".

Page 16: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 16

Пример. Тестируемый класс

public class FactorialClass

{

public static BigInteger Factorial(int number)

{

if (number < 0) throw new

ArgumentException("Argument is Less than Zero.");

if (number == 0) return 1;

else return Factorial(number - 1) * number;

}

public static double CircleSquare(double radius)

{

return 3.14 * radius * radius;

}

public static double CircleLength(double radius)

{

return 2.0 * 3.14 * radius;

}

}

Page 17: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 17

Пример. Класс-тест[TestClass]

public class UnitTest1 {

[TestMethod, ExpectedException(typeof(ArgumentException))]

public void TestFactorial() {

TDDExample.FactorialClass.Factorial(-100);

}

[TestMethod]

public void TestCircleSquare() {

double testRadius = 10;

double expectedResult = Math.PI * Math.Pow(testRadius, 2);

double actualResult = TDDExample.FactorialClass.CircleSquare(testRadius);

double tolerance=0.01;

Assert.AreEqual(expectedResult, actualResult, tolerance);

}

[TestMethod]

public void TestCircleLength() {

double testRadius = 10;

double expectedResult = 2.0 * Math.PI * testRadius;

double actualResult = TDDExample.FactorialClass.CircleLength(testRadius);

double tolerance = 0.01;

Assert.AreEqual(expectedResult, actualResult, tolerance);

}

}

Page 18: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 18

Результат

Page 19: C# Desktop. Занятие 17

http://www.slideshare.net/IgorShkulipa 19

Лабораторная работа №17. Unit-тестирование

В индивидуальных курсовых проектах при необходимости использоватьсоздание unit-тестов и TDD.