101
LOGO Части I, II, III Тестирование hwdtech.com УК 03.007.02-2011

ук 03.007.02 2011

Embed Size (px)

Citation preview

Page 1: ук 03.007.02 2011

LOGO

Части I, II, III

Тестирование

hwdtech.com УК 03.007.02-2011

Page 2: ук 03.007.02 2011

Цели тестирования

Page 3: ук 03.007.02 2011

Зачем тестирование нужно?

1

2

3

Полностью протестировать любую программу.

Тестирование позволит убедиться, что программа

работает правильно.

Тестировщик должен гарантировать правильность

выполнения программы.

Page 4: ук 03.007.02 2011

Это были самые распространенные заблуждения о тестировании

Page 5: ук 03.007.02 2011

Разберемся с ними подробнее…

Page 6: ук 03.007.02 2011

Стандартные возражения

Почему программисты вообще делают ошибки? Пусть они их не делают.

Сначала все напишем по-быстрому, а потом поправим все ошибки.

Сколько ошибок мы нашли? N – это много или мало?

Почему наши пользователи находят ошибки, если мы потратили на тестирование столько времени?!

Мы нашли N ошибок – мы можем остановить тестирование?

А как будет себя вести наше приложение в эксплуатации?

Заблуждения – это реакция на неудовлетворительные ответы на данные вопросы.

Page 7: ук 03.007.02 2011

Полностью протестировать любую

программу невозможно

• Проверить реакцию программы на каждую комбинацию входных данных – Есть корректные и некорректные входные данные

• Проверить каждую возможную последовательность выполнения команд программы – Мейерс, 1979

Написал программу из 100 строк, имеющую 108 последовательностей выполнения

Page 8: ук 03.007.02 2011

Тестирование позволит убедиться,

что программа работает правильно

• Правильность программы нельзя доказать логически – Можно проверить только соответствие спецификации

Page 9: ук 03.007.02 2011

Тестировщик должен гарантировать

правильность выполнения

программы

• 40-80% времени тратится на исправление ошибок

• 1,5 ошибки на один оператор программы

• Тестировщик тоже человек!

Page 10: ук 03.007.02 2011

Обсуждение

Ваши версии – зачем нужно тестирование?

Page 11: ук 03.007.02 2011

Качество

Page 12: ук 03.007.02 2011

Что такое качество?

• Качество ≠ отсутствие ошибок

В самом качественном автомобиле 2010 года выявляется в среднем 59 дефектов на 100 автомобилей в первые 90 дней.

• Удовлетворенность заказчика? Пациент, которому действия доктора причиняют боль.

• Соответствие ожиданиям: делает то, что должен, не делает того, что не должен

Page 13: ук 03.007.02 2011

Определение качества

ISO 9126

Качество ПО – совокупная характеристика ПО с учетом следующих составляющих: – Надежность

– Сопровождаемость

– Практичность

– Эффективность

– Мобильность

– Функциональность

Page 14: ук 03.007.02 2011

Определение качества

Надежность – набор атрибутов, относящихся к способности ПО сохранять свой уровень качества функционирования в установленных условиях за определенный период времени

• Уровень завершенности (отсутствие ошибок)

• Устойчивость к дефектам

• Восстанавливаемость

• Доступность

• Готовность

Page 15: ук 03.007.02 2011

Определение качества

Мобильность — набор атрибутов, относящихся к способности ПО быть перенесенным из одного окружения в другое

• Адаптируемость

• Простота установки

• Сосуществование

• Замещаемость

Page 16: ук 03.007.02 2011

Определение качества

Сопровождаемость - набор атрибутов, относящихся к объему работ, требуемых для проведения конкретных изменений (модификаций)

• Удобство анализа

• Изменяемость

• Стабильность

• Тестируемость

Page 17: ук 03.007.02 2011

Определение качества

Практичность (применимость) — набор атрибутов, относящихся к объему работ, требуемых для исполнения и индивидуальной оценки такого исполнения определенным или предполагаемым кругом пользователей

• Понятность

• Простота использования

• Изучаемость

• Привлекательность

Page 18: ук 03.007.02 2011

Определение качества

Эффективность — набор атрибутов, относящихся к соотношению между уровнем качества функционирования ПО и объемом используемых ресурсов при установленных условиях

• Временная эффективность

• Используемость ресурсов

Page 19: ук 03.007.02 2011

Определение качества

Функциональность — набор атрибутов характеризующий, соответствие функциональных возможностей ПО набору требуемой пользователем функциональности

• Пригодность к применению

• Корректность

• Способность к взаимодействию

• Защищенность

Page 20: ук 03.007.02 2011

Как получается Качество ПО

• Качество ПО зависит только от качества его процесса разработки

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

Page 21: ук 03.007.02 2011

Определение тестирования

Тестирование ПО - процесс исследования программного обеспечения (ПО) с целью получения информации о качестве продукта.

(Толковый словарь)

Дефект - изъян, порча, повреждение; недостаток, несовершенство.

Page 22: ук 03.007.02 2011

Влияние дефектов

PMBOK

Page 23: ук 03.007.02 2011

Влияние дефектов

Водопадная модель

Page 24: ук 03.007.02 2011

Влияние дефектов

По виду артефактов

Page 25: ук 03.007.02 2011

Влияние дефектов

Итеративная модель (снижение рисков)

Page 26: ук 03.007.02 2011

Влияние дефектов

С точки зрения управление рисками

Page 27: ук 03.007.02 2011

Влияние дефектов

С точки зрения размера проекта (Панкратов В.)

Page 28: ук 03.007.02 2011

Влияние дефектов

По степени автоматизации действий

Page 29: ук 03.007.02 2011

Соберем идеи

• Тестирование ПО больше, чем просто поиск дефектов!!!

• Тестирование – это часть процесса разработки, которое занимает 40-80% всего процесса разработки и стоит 30-50% от общей стоимости проекта

• Тестирование не только может выявлять дефекты, но и предотвращать их.

• Эффективность тестирования сильно влияет на стоимость проекта и сроки его завершения.

• Отказ от тестирования – это стратегия пассивного принятия рисков.

• Автоматизация тестирования должна приводить к снижению расходов на тестирование.

Page 30: ук 03.007.02 2011

Классификация видов

тестирования

По объекту тестирования:

• Функциональное тестирование

• Тестирование производительности – Нагрузочное тестирование

– Тестирование стабильности

– Стресс-тестирование

• Тестирование удобства использования

• Тестирование интерфейса пользователя

• Тестирование безопасности

• Тестирование локализации

• Тестирование совместимости

Page 31: ук 03.007.02 2011

По знанию системы: • Тестирование белого ящика

– Соответствие кода соглашениям по наименованию и по кодированию

– Корректная обработка ошибок – Выделение памяти – Покрытие кода: все ли операторы были выполнены хотя бы один

раз – Проверка всех путей управления модуля

• Тестирование черного ящика • Тестирование серого ящика По степени автоматизации: • Ручное тестирование • Автоматизированное тестирование • Полуавтоматизированное тестирование

Page 32: ук 03.007.02 2011

По степени автоматизации:

• Ручное тестирование

• Автоматизированное тестирование

• Полуавтоматизированное тестирование

По степени изолированности системы:

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

• Интеграционное тестирование

• Системное тестирование

Page 33: ук 03.007.02 2011

По степени позитивности сценариев:

• Позитивное тестирование

• Негативное тестирование

По степени подготовленности к тестированию:

• Тестирование по документации (формальное тестирование)

• Тестирование как есть (интуитивное тестирование)

Page 34: ук 03.007.02 2011

По времени проведения тестирования:

• Альфа-тестирование – Тестирование при приемке

– Тестирование новой функциональности

– Регрессионное тестирование

– Тестирование при сдаче

• Бета-тестирование

• Приемочное тестирование

Page 35: ук 03.007.02 2011

Логика Хоара

• Контрактная модель программирования

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

• Тройка Хоара {pred} statement {post}, где pred, post – утверждения (assertions), pred – предусловие, post - постусловие, statement – оператор языка программирования

Пример:

{x+1 == 43} y=x+1; {y == 43 ^ x == 42}

• Логика Хоара определяет аксиомы и правила вывода для императивного языка программирования

(http://ru.wikipedia.org/wiki/Логика_Хоара)

Page 36: ук 03.007.02 2011

Правила Логики Хоара

Аксиома пустого оператора

{P} skip {P}

Аксиома присваивания

{P[E/x]} x := E {P}

Правило композиции

{P} S {Q}, {Q} T {R} ╞ {P} S;T {R}

Правило условного оператора

{B ^ P} S {Q}, {B’ ^P} T {Q} ╞ {P} if B then S else T endif {Q}

Правило вывода

P1 → P, {P} S {Q}, Q → Q1 ╞ {P1} S {Q1}

Правило оператора цикла

{P ^ B} S {P} ╞ {P} while B do S done {B’ ^ P}

Page 37: ук 03.007.02 2011

От формальной системы к

автоматическому тестированию

• Все последовательности операторов протестировать

невозможно

• Часто тестирование – это многократно повторяющиеся рутинные действия

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

• Часто проверку результатов на соответствие требованиям заказчика также можно автоматизировать.

Page 38: ук 03.007.02 2011

Разминка

Соберите фигуру на слайде

Page 39: ук 03.007.02 2011

Модульное (юнит)

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

• С помощью правила композиции и/или правила вывода объединяем несколько операторов в один общий блок. Проверка предусловия и постусловия для блока операторов равносильна проверке пост- и предусловий каждого из операторов в этом блоке.

Пример: {x + 1 ==43 } y = x + 1; {y == 43}

{y == 43} z = y; {z == 43}

По правилу композиции

{x + 1 == 43} y = x + 1; z = y; {z == 43}

Page 40: ук 03.007.02 2011

• Какие границы блоков удобнее выбирать для целей тестирования? – Методы (см. Контрактная модель программирования)

{pred} void f(object arg1)… {post}

– Классы (как контейнер методов)

• Часто при разработке кода делаются неявные предположения о состоянии программы (Asserts) Исследования: На каждые 5-6 строк делается как минимум одно

неявное предположение о состоянии программы

Вывод: Рекомендация по рефакторингу – методы должны быть короткими (5-7 строк)

Page 41: ук 03.007.02 2011

Следствия

• Пишутся на том же языке, что и тестируемая процедура или класс

• Юнит-тесты должны быть простыми!!!

Плюсы

• Стимулируют рефакторинг

• Поощряют написание слабосвязанного кода

• Упрощают регрессионное тестирование

• Юнит-тесты = документация

Ограничения

• Не проверяют взаимодействие компонентов

• Не дают 100% гарантии

• Сложно покрывать тестами уже написанное приложение

Page 42: ук 03.007.02 2011

Интеграционное тестирование с

точки зрения автоматизации

• Есть несколько методов, каждый из которых покрыт тестами

• Эти методы используются для реализации функции верхнего уровня

• Покрытие тестами этой функции и есть интеграционное тестирование

Замечание: Покрытие тестами только

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

Page 43: ук 03.007.02 2011

Критерий остановки

• На один метод как правило пишется несколько тестов

Когда пора остановиться?

Варианты:

• По времени – очень плохой критерий

• Вычислять коэффициент покрытия кода – не всегда есть под рукой инструменты для вычисления покрытия кода, нет 100% гарантии

• Test Driven Development

Page 44: ук 03.007.02 2011

Test-Driven Development

Написание тестов

Тесты не компилируются

Определение интерфейсов

Тесты не проходят

Написание кода

Тесты проходят

Рефакторинг

Page 45: ук 03.007.02 2011

Разминка

Загадано слово.

Можно задавать вопросы только с ответами да/нет.

Угадайте за минимальное количество вопросов.

Page 46: ук 03.007.02 2011

Критерий “хорошего” теста

• Существует обоснованная вероятность выявления тестом ошибки

• Набор тестов не должен быть избыточным

• Тест должен быть наилучшим в своей категории

• Не должен быть слишком простым и слишком сложным

Page 47: ук 03.007.02 2011

Разработка тестов

• Классы эквивалентности

• Граничные условия

• Stubs

• Mocks

Page 48: ук 03.007.02 2011

JUnit

import org.junit.Test;

import junit.framework.Assert;

public class MathTest

{

@Test

public void testEquals()

{

Assert.assertEquals(4, 2 + 2);

Assert.assertTrue(4 == 2 + 2);

}

@Test

public void testNotEquals()

{

Assert.assertFalse(5 == 2 + 2);

}

}

public class TestClass extends TestCase

{

public TestClass(String testName)

{ super(testName); }

@Test

public void testFactorialNull()

{

MathFunc math = new MathFunc(); assertTrue(math.factorial() == 1);

}

@Test

public void testFactorialPositive()

{

MathFunc math = new MathFunc(5); assertTrue(math.factorial() == 120);

}

@Test

public void testPlus()

{

MathFunc math = new MathFunc(45); assertTrue(math.plus(123) == 168);

}

}

Page 49: ук 03.007.02 2011

junit.framework.Assert

• assertEquals

• assertFalse

• assertNotNull

• assertNull

• assertNotSame

• assertSame

• assertTrue

Page 50: ук 03.007.02 2011

Классы эквивалентности

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

Группа тестов представляет собой класс эквивалентности, если:

Page 51: ук 03.007.02 2011

Классы эквивалентности

• Все тесты предназначены для выявления одной и той же ошибки

• Если один из тестов выявит ошибку, то остальные скорее всего тоже это сделают

• Если один из тестов не выявит ошибки, то остальные скорее всего тоже этого не сделают

Page 52: ук 03.007.02 2011

Классы экивалентности

• Тесты включают значения одних и тех же входных данных

• Для их проведения выполняются одни и те же операции

• В результате тестов формируются значения одних и тех же выходных данных

• Либо не один из тестов не вызывает обработку ошибок в программе, либо всеми тестами вызывается одна и та же обработка ошибок

Page 53: ук 03.007.02 2011

Пример классов

эквивалентности

Решение квадратного уравнения в вещественных числах

Result SquareRoot(double a, double b, double c);

• Уравнение, имеющее решение в виде двух корней кратности 1 – (1, -1, -2)

• Уравнение, имеющее решение в виде одного корня кратности 2 – (1, 2, 1)

• Уравнение, не имеющее решений – (1, 0, 1)

• Коэффициент a = 0

Page 54: ук 03.007.02 2011

Разминка

Определить класс эквивалентности

Page 55: ук 03.007.02 2011

Способы выявления

классов эквивалентности

• Заведомо неверные или недопустимые данные Пример: a = 0 с предыдущего слайда

Page 56: ук 03.007.02 2011

• Диапазоны числовых значений I. Для диапазона значений есть три недопустимых класса

экивалентности:

– Числа меньше диапазона

– Числа больше диапазона

– Нечисловые данные

Замечание: Иногда некоторые из этих классов могут отсутствовать, например, нет ограничения сверху. Лучше явно убедиться, что этого ограничения нет, взяв очень большое число.

II. Поддиапазоны, например, 1-5, 9, 10, 12, 14, 16 – этажность зданий

Page 57: ук 03.007.02 2011

• Фиксированные перечни значений – Все значения данного перечня

– Любое значение, не входящее в перечень

Например, улицы г. Омска

Идеи для поиска классов эквивалентности

– Аббревиатуры

– Сокращения

– Ошибки при написании

– Старые названия

Page 58: ук 03.007.02 2011

• Списки меню, выбора Любой элемент меню может представлять отдельный класс

эквивалентности

• Переменные, значения которых должны быть равными Значения, которые являются приемлемыми, но не принимаются в

данном месте программы, образуют отдельные эквивалентности

Пример: дата 13-07-2011, 07-13-2011, 13.07.2011, 13/07/2011 числа с плавающей точкой 12,43 12.43

Page 59: ук 03.007.02 2011

• Значения, зависящие от времени Пример: запрос серверу, когда

– Ничего не обрабатывается

– Идет обработка другого запроса

– Сразу после завершения обработки другого запроса

• Группы переменных, результат которых ограничивается определенным набором или диапазоном значений Пример: квадратное уравнение

Page 60: ук 03.007.02 2011

• Действия, на которые программа отвечает эквивалентными событиями Пример, обработка ошибок

• Различные варианты окружения Пример, объем оперативный памяти:

– Проектный

– Недостаточный

– Больше, чем проектный

Page 61: ук 03.007.02 2011

Граничные условия

• Для каждого класса эквивалентности нужно провести минимальное число тестов Следовательно: Лучшие тесты – те, которые лежат на границах

классов эквивалентности

Пример, для квадратного уравнения лучше брать не 0, а число, чуть меньше “эпсилон”

Page 62: ук 03.007.02 2011

Разминка

“Самолетики”

Page 63: ук 03.007.02 2011

Stubs

Зависимость – это объект системы, с котором взаимодействует тестируемый код и над которым нет контроля у разработчика тестов.

Примеры: – Объекты операционной системы

– Объекты, разработка которых еще не была завершена/начата

– Сторонние библиотеки

Заглушка – контролируемая замена зависимости в разрабатываемой системе

Page 64: ук 03.007.02 2011

Когда применяются

заглушки

• Создать имитацию загрузки или ограниченности ресурсов

• Создать имитацию сбоя в системе

• Выполнить тестирование, когда зависимость еще не реализована

• Гарантировать отсутствие влияния зависимости на результаты тестирования

• Отладка тестов для фасада

Page 65: ук 03.007.02 2011

Идеи по реализации

заглушек

• Заглушка имитирует поведение реального объекта – применяем паттерн Прокси

• Код должен, использующий базовый интерфейс для Заглушек и реальных объектов, должен удовлетворять принципу подстановки Лисков

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

Page 66: ук 03.007.02 2011

Mocks

Тестирование основанное на состояниях (традиционный подход)

Недостатки: – Требует знания о внутреннем состоянии объекта –возможно

нарушение инкапсуляции

– Нарушает принципы ООП

Page 67: ук 03.007.02 2011

Тестирование основанное на поведении – сосредоточено на том, какие методы вызываются, в какой последовательности, какие результаты выдают

Поведенческое тестирование – тестирование того, как объект взаимодействует с другими объектами, то есть посылает выходные данные и принимает входные от других объектов.

Page 68: ук 03.007.02 2011

Mock-объект – прокси-объект, который определяет прошел ли тестируемый объект тест или нет

Различие между Stub и Mock:

• Stub подменяет реальный объект с целью имитации реального функционала

• Mock подменяет реальный объект с целью оценки правильности взаимодействия тестируемого объекта с подменяемым.

Page 69: ук 03.007.02 2011

Подходы к реализации mock

• Proxy (easymock, jmock, moq, rhino.mocks)

• Подгрузка класса mock объекта вместо реального класса

(jmockit, powermock, DI контейнеры)

Page 70: ук 03.007.02 2011

Библиотека EasyMock

IFoo mock = EasyMock.createMock(IFoo.class);

EasyMock.expect(mock.doSomething(“argument”)).andReturn(true);

EasyMock.replay(mock);

bool result = test.perform();

EasyMock.verify(mock);

Page 71: ук 03.007.02 2011

Проверка поведения метода

• andExpectThrow(exception)

• ExpectLastCall();

• times(min, max)

• AnyTimes()

• AtLeastOnce()

Page 72: ук 03.007.02 2011

Параметры метода

• eq(value)

• isA(class)

• anyBoolean(), anyByte(), anyChar(), anyDouble(), …

• IsNull()

• NotNull()

• startsWith(string), contains(string), endsWith(string)

• matches(regexp), find(regexp)

expect(mockDao.loadByUsernameAndPassword(eq(userName),

eq(passwordHash))) .andReturn(results);

Page 73: ук 03.007.02 2011

Пример теста

import junit.framework.TestCase;

import static org.easymock.EasyMock.createStrictMock;

import static org.easymock.EasyMock.expect;

import static org.easymock.EasyMock.replay;

import static org.easymock.EasyMock.verify;

import static org.easymock.EasyMock.eq;

public class LoginServiceTest extends TestCase

{

private LoginServiceImpl service;

private UserDAO mockDao;

@Override public void setUp()

{

service = new LoginServiceImpl();

mockDao = createStrictMock(UserDAO.class);

service.setUserDAO(mockDao);

}

Page 74: ук 03.007.02 2011

public void testSuccsessScenario()

{

User results = new User();

String userName = "testUserName";

String password = "testPassword";

String passwordHash = " Ӷ&I7 Ni=.";

expect(mockDao.loadByUsernameAndPassword(eq(userName), eq(passwordHash))) .andReturn(results);

replay(mockDao);

assertTrue(service.login(userName, password));

verify(mockDao);

}

}

Page 75: ук 03.007.02 2011

Библиотека Moq

Методы

1. Вызов метода

var mock = new Mock<IFoo>();

mock.Setup(foo => foo.DoSomething("ping")).Returns(true);

2. Выходные параметры var outString = "ack";

mock.Setup(foo => foo.TryParse("ping", out outString)).Returns(true);

3. Входно-выходные параметры var instance = new Bar();

mock.Setup(foo => foo.Submit(ref instance)).Returns(true);

Page 76: ук 03.007.02 2011

4. Досуп к параметру

mock.Setup(x => x.DoSomething(It.IsAny<string>()))

.Returns((string s) => s.ToLower());

5. Генерация исключений

mock.Setup(foo =>

foo.DoSomething("reset")).Throws<InvalidOperationException>();

mock.Setup(foo => foo.DoSomething("")).Throws(new

ArgumentException("command");

6. Подстановка возвращаемого значения

mock.Setup(foo => foo.GetCount()).Returns(() => count);

Page 77: ук 03.007.02 2011

7. Возврат разных значений на каждый вызов функции

var mock = new Mock<IFoo>();

var calls = 0;

mock.Setup(foo => foo.GetCountThing())

.Returns(() => calls)

.Callback(() => calls++);

Console.WriteLine(mock.Object.GetCountThing());

Page 78: ук 03.007.02 2011

8. Возращение значений в зависимости от значений входных параметров

mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Returns(true);

mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true);

mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10,

Range.Inclusive))).Returns(true);

mock.Setup(x => x.DoSomething(It.IsRegex("[a-d]+",

RegexOptions.IgnoreCase))).Returns("foo");

Page 79: ук 03.007.02 2011

9. Свойства mock.Setup(foo => foo.Name).Returns("bar");

mock.Setup(foo => foo.Bar.Baz.Name).Returns("baz");

mock.SetupSet(foo => foo.Name = "foo");

mock.VerifySet(foo => foo.Name = "foo");

mock.SetupProperty(f => f.Name);

mock.SetupProperty(f => f.Name, "foo");

Page 80: ук 03.007.02 2011

10. Обратный вызов функций из mock-объекта

var mock = new Mock<IFoo>();

mock.Setup(foo => foo.Execute("ping")).Returns(true).Callback(() =>

calls++);

mock.Setup(foo => foo.Execute(It.IsAny<string>())).Returns(true)

.Callback((string s) => calls.Add(s));

mock.Setup(foo => foo.Execute(It.IsAny<string>())).Returns(true)

.Callback<string>(s => calls.Add(s));

mock.Setup(foo => foo.Execute(It.IsAny<int>(), It.IsAny<string>()))

.Returns(true)

.Callback<int, string>((i, s) => calls.Add(s));

Page 81: ук 03.007.02 2011

mock.Setup(foo => foo.Execute("ping"))

.Callback(() => Console.WriteLine("Before returns"))

.Returns(true)

.Callback(() => Console.WriteLine("After returns"));

Page 82: ук 03.007.02 2011

Проверки 1. Вызов метода

mock.Verify(foo => foo.Execute("ping"));

mock.Verify(foo => foo.Execute("ping"), "When doing operation X, the

service should be pinged always");

2. Количество вызовов метода

mock.Verify(foo => foo.Execute("ping"), Times.Never());

mock.Verify(foo => foo.Execute("ping"), Times.AtLeastOnce());

Page 83: ук 03.007.02 2011

3. Свойства

mock.VerifyGet(foo => foo.Name);

mock.VerifySet(foo => foo.Name);

mock.VerifySet(foo => foo.Name ="foo");

mock.VerifySet(foo => foo.Value = It.IsInRange(1, 5, Range.Inclusive));

Page 84: ук 03.007.02 2011

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

пароля – шаг 1

public void When_user_forgot_password_should_save_user()

{

var stubUserRepository = mockRepository.Create<IUserRepository>();

var stubbedSmsSender = mockRepository.Create<ISmsSender>();

var theUser = new User{HashedPassword = "this is not hashed password"};

stubUserRepository.Setup(x => x.GetUserByName("ayende")).Return(theUser).Verifiable();

var controllerUnderTest = new LoginController(stubUserRepository.Object, stubbedSmsSender.Object);

controllerUnderTest.ForgotMyPassword("ayende");

stubUserRepository.AssertWasCalled( x => x.Save(user));

}

public void ForgotMyPassword(string username)

{

var user = users.GetUserByName(username);

users.Save(user);

}

Page 85: ук 03.007.02 2011

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

пароля – шаг 2

public void When_user_forgot_password_should_reset_password()

{

var stubUserRepository = mockRepository.Create<IUserRepository>();

var stubbedSmsSender = MockRepository.Create<ISmsSender>();

var theUser = new User{HashedPassword = "this is not hashed password"}; stubUserRepository.Setup(x => x.GetUserByName("ayende")).Return(theUser);

var controllerUnderTest = new LoginController(stubUserRepository.Object, stubbedSmsSender.Object);

controllerUnderTest.ForgotMyPassword("ayende");

Assert.AreNotEqual("this is not hashed password", theUser.HashedPassword);

}

public void ForgotMyPassword(string username)

{

var user = users.GetUserByName(username);

user.HashedPassword = "new pass";

users.Save(user);

}

Page 86: ук 03.007.02 2011

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

пароля – шаг 3

public void When_user_forgot_password_should_save_user()

{

var mockUserRepository = mockRepository.Create<IUserRepository>();

var stubbedSmsSender = mockRepository.Create<ISmsSender>();

var theUser = new User{HashedPassword = "this is not hashed password"};

mockUserRepository.Setup(x => x.GetUserByName("ayende")).Return(theUser);

mockUserRepository.Setup ( x => x.Save(theUser) ).Verifiable();

var controllerUnderTest = new LoginController(mockUserRepository.Object, stubbedSmsSender.Object);

controllerUnderTest.ForgotMyPassword("ayende");

mockUserRepository.VerifyAll();

}

public void ForgotMyPassword(string username)

{

var user = users.GetUserByName(username);

user.HashedPassword = "new pass";

users.Save(user);

}

Page 87: ук 03.007.02 2011

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

пароля – шаг 4

public void When_user_forgot_password_should_sms_user()

{

var stubUserRepository = mockRepository.Create<IUserRepository>();

var stubbedSmsSender = mockRepository.Create<ISmsSender>();

var theUser = new User{HashedPassword = "this is not hashed password", Phone = "1234-1234"};

stubUserRepository.Stub(x => x.GetUserByName("ayende")).Return(theUser);

var controllerUnderTest = new LoginController(stubUserRepository.Object, stubbedSmsSender.Object);

controllerUnderTest.ForgotMyPassword("ayende");

stubbedSmsSender.AssertWasCalled( x => x.Send( Arg.Is.Equal("1234-1234"), Arg.Text.StartsWith("Password was changed to:") ));

}

public void ForgotMyPassword(string username)

{

var user = users.GetUserByName(username);

user.HashedPassword = "new pass";

users.Save(user);

smsSender.Send(user.Phone, "Password was changed to: new pass");

}

Page 88: ук 03.007.02 2011

Пример: заглушка для еще

не написанного объекта

Interface IUserStorage

{

bool Save(User user);

bool Connect(string userName);

}

Page 89: ук 03.007.02 2011

Пример: заглушка для еще

не написанного объекта

class AbstractFactory

{

IUserStorage Create()

{

Mock<IUserStorage> storage = mockRepository.Create<IUserStrorage>();

storage.Setup( s => s.Save(It.IsAny<User>())).Returns(true);

storage.Setup(s => s.Connect(“ayende”)).Returns(true);

storage.Setup(s => s.Connect(It.Not.IsEqual<string>(“ayende”))).Returns(false);

return storage.Object; }

MockRepository mockRepository = new MockRepository(MockBehavior.Strict);

}

Page 90: ук 03.007.02 2011

Пример тестирования через

mock-объект

Пример 03.007.02-2011.01

Page 91: ук 03.007.02 2011

Пример: модульное

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

Пример 03.007.02-2011.03

Page 92: ук 03.007.02 2011

Пример: отладка тестов

через mock-объекты

Пример 03.007.02-2011.02

Мок-объекты использованы для отладки самих тестов

Page 93: ук 03.007.02 2011

Пример: нагрузочные тесты

Пример 03.007.02-2011.05

Page 94: ук 03.007.02 2011

Идеи для применения mock

• Тестирование сложности алгоритмов

• Графический интерфейс

Page 95: ук 03.007.02 2011

Пример: тестирование

пользовательского интерфейса

Puppeteer, Вальтер Антон (http://blogr.avalter.net/2009/06/puppeteer.html)

• АОП или использование aссessors

• Требует написания кода для обработки элементарных типов пользовательского интерфейса

Page 96: ук 03.007.02 2011

[PuppetMethod("Click",typeof(ClickParamCreator))]

private void button1_Click_1(object sender, EventArgs e)

{ //.....

}

public class ClickParamCreator : Puppeteer.IParamsCreator { public object[] CreateParams(Dictionary<string,string> parameters)

{ object[] res = new object[2]; res[0] = null; res[1] = new EventArgs(); return res; } }

Page 97: ук 03.007.02 2011

public partial class Form1 : Form

{ // ............ [PuppetChild("TextBox")] [ReflectedPuppetProperty("Text","Text",typeof(SingleStringParamCreator))] private System.Windows.Forms.TextBox textBox1; // ............

}

Page 98: ук 03.007.02 2011

Puppeteer.Puppeteer puppeteer = new Puppeteer.Puppeteer();

puppeteer.LoadApplication(PathToExe); ITestAction action = new Puppeteer.Actions.Action(new SetProperty("Name", "Text", "Иванов Иван action.PreConditions.Add(new AssertEqual(new GetProperty("Name", "Text"), "")); action.PostConditions.Add(new AssertEqual(new GetProperty("Name", "Text"), "Иванов Иван")); puppeteer.AddAction(action);

action = new Puppeteer.Actions.Action(new SetProperty("EMail", "Text", "[email protected]")); action.PreConditions.Add(new AssertEqual(new GetProperty("EMail", "Text"), "")); action.PostConditions.Add(new AssertEqual(new GetProperty("EMail", "Text"), "[email protected]")); puppeteer.AddAction(action); action = new Puppeteer.Actions.Action(new SetProperty("Private", "Selected", true.ToString())); action.PostConditions.Add(new AssertEqual(new GetProperty("Private", "Selected"), true.ToString())); puppeteer.AddAction(action); action = new Puppeteer.Actions.Action(new InvokeMethod("Main", "Click"));

action.PreConditions.Add(new AssertEqual(new GetProperty("EMail", "Text"), "[email protected]")); action.PreConditions.Add(new AssertEqual(new GetProperty("Name", "Text"), "Иванов Иван")); action.PreConditions.Add(new AssertEqual(new GetProperty("Private", "Selected"), true.ToString())); action.PostConditions.Add(new AssertEqual(new GetProperty("List", "Items", 0), "[P] Иванов Иван [email protected]")); puppeteer.AddAction(action);

Page 99: ук 03.007.02 2011

puppeteer.Run(new Dictionary<string, string>());

textBox1.Text = puppeteer.Result;

PuppetHolder.Clear();

Page 100: ук 03.007.02 2011

Пример: тестирование

сложности алгоритмов

Пример 03.007.02-2011.04

Page 101: ук 03.007.02 2011

LOGO hwdtech.com