Upload
etyumentcev
View
251
Download
2
Embed Size (px)
Citation preview
LOGO
Части I, II, III
Тестирование
hwdtech.com УК 03.007.02-2011
Цели тестирования
Зачем тестирование нужно?
1
2
3
Полностью протестировать любую программу.
Тестирование позволит убедиться, что программа
работает правильно.
Тестировщик должен гарантировать правильность
выполнения программы.
Это были самые распространенные заблуждения о тестировании
Разберемся с ними подробнее…
Стандартные возражения
Почему программисты вообще делают ошибки? Пусть они их не делают.
Сначала все напишем по-быстрому, а потом поправим все ошибки.
Сколько ошибок мы нашли? N – это много или мало?
Почему наши пользователи находят ошибки, если мы потратили на тестирование столько времени?!
Мы нашли N ошибок – мы можем остановить тестирование?
А как будет себя вести наше приложение в эксплуатации?
Заблуждения – это реакция на неудовлетворительные ответы на данные вопросы.
Полностью протестировать любую
программу невозможно
• Проверить реакцию программы на каждую комбинацию входных данных – Есть корректные и некорректные входные данные
• Проверить каждую возможную последовательность выполнения команд программы – Мейерс, 1979
Написал программу из 100 строк, имеющую 108 последовательностей выполнения
Тестирование позволит убедиться,
что программа работает правильно
• Правильность программы нельзя доказать логически – Можно проверить только соответствие спецификации
Тестировщик должен гарантировать
правильность выполнения
программы
• 40-80% времени тратится на исправление ошибок
• 1,5 ошибки на один оператор программы
• Тестировщик тоже человек!
Обсуждение
Ваши версии – зачем нужно тестирование?
Качество
Что такое качество?
• Качество ≠ отсутствие ошибок
В самом качественном автомобиле 2010 года выявляется в среднем 59 дефектов на 100 автомобилей в первые 90 дней.
• Удовлетворенность заказчика? Пациент, которому действия доктора причиняют боль.
• Соответствие ожиданиям: делает то, что должен, не делает того, что не должен
Определение качества
ISO 9126
Качество ПО – совокупная характеристика ПО с учетом следующих составляющих: – Надежность
– Сопровождаемость
– Практичность
– Эффективность
– Мобильность
– Функциональность
Определение качества
Надежность – набор атрибутов, относящихся к способности ПО сохранять свой уровень качества функционирования в установленных условиях за определенный период времени
• Уровень завершенности (отсутствие ошибок)
• Устойчивость к дефектам
• Восстанавливаемость
• Доступность
• Готовность
Определение качества
Мобильность — набор атрибутов, относящихся к способности ПО быть перенесенным из одного окружения в другое
• Адаптируемость
• Простота установки
• Сосуществование
• Замещаемость
Определение качества
Сопровождаемость - набор атрибутов, относящихся к объему работ, требуемых для проведения конкретных изменений (модификаций)
• Удобство анализа
• Изменяемость
• Стабильность
• Тестируемость
Определение качества
Практичность (применимость) — набор атрибутов, относящихся к объему работ, требуемых для исполнения и индивидуальной оценки такого исполнения определенным или предполагаемым кругом пользователей
• Понятность
• Простота использования
• Изучаемость
• Привлекательность
Определение качества
Эффективность — набор атрибутов, относящихся к соотношению между уровнем качества функционирования ПО и объемом используемых ресурсов при установленных условиях
• Временная эффективность
• Используемость ресурсов
Определение качества
Функциональность — набор атрибутов характеризующий, соответствие функциональных возможностей ПО набору требуемой пользователем функциональности
• Пригодность к применению
• Корректность
• Способность к взаимодействию
• Защищенность
Как получается Качество ПО
• Качество ПО зависит только от качества его процесса разработки
• Качество процесса разработки зависит только от культуры разработки самой проектной команды
Определение тестирования
Тестирование ПО - процесс исследования программного обеспечения (ПО) с целью получения информации о качестве продукта.
(Толковый словарь)
Дефект - изъян, порча, повреждение; недостаток, несовершенство.
Влияние дефектов
PMBOK
Влияние дефектов
Водопадная модель
Влияние дефектов
По виду артефактов
Влияние дефектов
Итеративная модель (снижение рисков)
Влияние дефектов
С точки зрения управление рисками
Влияние дефектов
С точки зрения размера проекта (Панкратов В.)
Влияние дефектов
По степени автоматизации действий
Соберем идеи
• Тестирование ПО больше, чем просто поиск дефектов!!!
• Тестирование – это часть процесса разработки, которое занимает 40-80% всего процесса разработки и стоит 30-50% от общей стоимости проекта
• Тестирование не только может выявлять дефекты, но и предотвращать их.
• Эффективность тестирования сильно влияет на стоимость проекта и сроки его завершения.
• Отказ от тестирования – это стратегия пассивного принятия рисков.
• Автоматизация тестирования должна приводить к снижению расходов на тестирование.
Классификация видов
тестирования
По объекту тестирования:
• Функциональное тестирование
• Тестирование производительности – Нагрузочное тестирование
– Тестирование стабильности
– Стресс-тестирование
• Тестирование удобства использования
• Тестирование интерфейса пользователя
• Тестирование безопасности
• Тестирование локализации
• Тестирование совместимости
По знанию системы: • Тестирование белого ящика
– Соответствие кода соглашениям по наименованию и по кодированию
– Корректная обработка ошибок – Выделение памяти – Покрытие кода: все ли операторы были выполнены хотя бы один
раз – Проверка всех путей управления модуля
• Тестирование черного ящика • Тестирование серого ящика По степени автоматизации: • Ручное тестирование • Автоматизированное тестирование • Полуавтоматизированное тестирование
По степени автоматизации:
• Ручное тестирование
• Автоматизированное тестирование
• Полуавтоматизированное тестирование
По степени изолированности системы:
• Модульное тестирование
• Интеграционное тестирование
• Системное тестирование
По степени позитивности сценариев:
• Позитивное тестирование
• Негативное тестирование
По степени подготовленности к тестированию:
• Тестирование по документации (формальное тестирование)
• Тестирование как есть (интуитивное тестирование)
По времени проведения тестирования:
• Альфа-тестирование – Тестирование при приемке
– Тестирование новой функциональности
– Регрессионное тестирование
– Тестирование при сдаче
• Бета-тестирование
• Приемочное тестирование
Логика Хоара
• Контрактная модель программирования
• Используется для доказательства частичной и полной корректности компьютерных программ
• Тройка Хоара {pred} statement {post}, где pred, post – утверждения (assertions), pred – предусловие, post - постусловие, statement – оператор языка программирования
Пример:
{x+1 == 43} y=x+1; {y == 43 ^ x == 42}
• Логика Хоара определяет аксиомы и правила вывода для императивного языка программирования
(http://ru.wikipedia.org/wiki/Логика_Хоара)
Правила Логики Хоара
Аксиома пустого оператора
{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}
От формальной системы к
автоматическому тестированию
• Все последовательности операторов протестировать
невозможно
• Часто тестирование – это многократно повторяющиеся рутинные действия
• Человек преимущественно необходим только на этапе оценки результатов, выданных ПО, на их соответствие требованиям заказчика.
• Часто проверку результатов на соответствие требованиям заказчика также можно автоматизировать.
Разминка
Соберите фигуру на слайде
Модульное (юнит)
тестирование
• С помощью правила композиции и/или правила вывода объединяем несколько операторов в один общий блок. Проверка предусловия и постусловия для блока операторов равносильна проверке пост- и предусловий каждого из операторов в этом блоке.
Пример: {x + 1 ==43 } y = x + 1; {y == 43}
{y == 43} z = y; {z == 43}
По правилу композиции
{x + 1 == 43} y = x + 1; z = y; {z == 43}
• Какие границы блоков удобнее выбирать для целей тестирования? – Методы (см. Контрактная модель программирования)
{pred} void f(object arg1)… {post}
– Классы (как контейнер методов)
• Часто при разработке кода делаются неявные предположения о состоянии программы (Asserts) Исследования: На каждые 5-6 строк делается как минимум одно
неявное предположение о состоянии программы
Вывод: Рекомендация по рефакторингу – методы должны быть короткими (5-7 строк)
Следствия
• Пишутся на том же языке, что и тестируемая процедура или класс
• Юнит-тесты должны быть простыми!!!
Плюсы
• Стимулируют рефакторинг
• Поощряют написание слабосвязанного кода
• Упрощают регрессионное тестирование
• Юнит-тесты = документация
Ограничения
• Не проверяют взаимодействие компонентов
• Не дают 100% гарантии
• Сложно покрывать тестами уже написанное приложение
Интеграционное тестирование с
точки зрения автоматизации
• Есть несколько методов, каждый из которых покрыт тестами
• Эти методы используются для реализации функции верхнего уровня
• Покрытие тестами этой функции и есть интеграционное тестирование
Замечание: Покрытие тестами только
верхнеуровневой функции не принесет много пользы, т.к. не проведено модульное тестирование самой функции, а значит нет возможности локализовать ошибку
Критерий остановки
• На один метод как правило пишется несколько тестов
Когда пора остановиться?
Варианты:
• По времени – очень плохой критерий
• Вычислять коэффициент покрытия кода – не всегда есть под рукой инструменты для вычисления покрытия кода, нет 100% гарантии
• Test Driven Development
Test-Driven Development
Написание тестов
Тесты не компилируются
Определение интерфейсов
Тесты не проходят
Написание кода
Тесты проходят
Рефакторинг
Разминка
Загадано слово.
Можно задавать вопросы только с ответами да/нет.
Угадайте за минимальное количество вопросов.
Критерий “хорошего” теста
• Существует обоснованная вероятность выявления тестом ошибки
• Набор тестов не должен быть избыточным
• Тест должен быть наилучшим в своей категории
• Не должен быть слишком простым и слишком сложным
Разработка тестов
• Классы эквивалентности
• Граничные условия
• Stubs
• Mocks
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);
}
}
junit.framework.Assert
• assertEquals
• assertFalse
• assertNotNull
• assertNull
• assertNotSame
• assertSame
• assertTrue
Классы эквивалентности
Если при выполнении двух тестов ожидается один и тот же результат, то они считаются эквивалентными.
Группа тестов представляет собой класс эквивалентности, если:
Классы эквивалентности
• Все тесты предназначены для выявления одной и той же ошибки
• Если один из тестов выявит ошибку, то остальные скорее всего тоже это сделают
• Если один из тестов не выявит ошибки, то остальные скорее всего тоже этого не сделают
Классы экивалентности
• Тесты включают значения одних и тех же входных данных
• Для их проведения выполняются одни и те же операции
• В результате тестов формируются значения одних и тех же выходных данных
• Либо не один из тестов не вызывает обработку ошибок в программе, либо всеми тестами вызывается одна и та же обработка ошибок
Пример классов
эквивалентности
Решение квадратного уравнения в вещественных числах
Result SquareRoot(double a, double b, double c);
• Уравнение, имеющее решение в виде двух корней кратности 1 – (1, -1, -2)
• Уравнение, имеющее решение в виде одного корня кратности 2 – (1, 2, 1)
• Уравнение, не имеющее решений – (1, 0, 1)
• Коэффициент a = 0
Разминка
Определить класс эквивалентности
Способы выявления
классов эквивалентности
• Заведомо неверные или недопустимые данные Пример: a = 0 с предыдущего слайда
• Диапазоны числовых значений I. Для диапазона значений есть три недопустимых класса
экивалентности:
– Числа меньше диапазона
– Числа больше диапазона
– Нечисловые данные
Замечание: Иногда некоторые из этих классов могут отсутствовать, например, нет ограничения сверху. Лучше явно убедиться, что этого ограничения нет, взяв очень большое число.
II. Поддиапазоны, например, 1-5, 9, 10, 12, 14, 16 – этажность зданий
• Фиксированные перечни значений – Все значения данного перечня
– Любое значение, не входящее в перечень
Например, улицы г. Омска
Идеи для поиска классов эквивалентности
– Аббревиатуры
– Сокращения
– Ошибки при написании
– Старые названия
• Списки меню, выбора Любой элемент меню может представлять отдельный класс
эквивалентности
• Переменные, значения которых должны быть равными Значения, которые являются приемлемыми, но не принимаются в
данном месте программы, образуют отдельные эквивалентности
Пример: дата 13-07-2011, 07-13-2011, 13.07.2011, 13/07/2011 числа с плавающей точкой 12,43 12.43
• Значения, зависящие от времени Пример: запрос серверу, когда
– Ничего не обрабатывается
– Идет обработка другого запроса
– Сразу после завершения обработки другого запроса
• Группы переменных, результат которых ограничивается определенным набором или диапазоном значений Пример: квадратное уравнение
• Действия, на которые программа отвечает эквивалентными событиями Пример, обработка ошибок
• Различные варианты окружения Пример, объем оперативный памяти:
– Проектный
– Недостаточный
– Больше, чем проектный
Граничные условия
• Для каждого класса эквивалентности нужно провести минимальное число тестов Следовательно: Лучшие тесты – те, которые лежат на границах
классов эквивалентности
Пример, для квадратного уравнения лучше брать не 0, а число, чуть меньше “эпсилон”
Разминка
“Самолетики”
Stubs
Зависимость – это объект системы, с котором взаимодействует тестируемый код и над которым нет контроля у разработчика тестов.
Примеры: – Объекты операционной системы
– Объекты, разработка которых еще не была завершена/начата
– Сторонние библиотеки
Заглушка – контролируемая замена зависимости в разрабатываемой системе
Когда применяются
заглушки
• Создать имитацию загрузки или ограниченности ресурсов
• Создать имитацию сбоя в системе
• Выполнить тестирование, когда зависимость еще не реализована
• Гарантировать отсутствие влияния зависимости на результаты тестирования
• Отладка тестов для фасада
Идеи по реализации
заглушек
• Заглушка имитирует поведение реального объекта – применяем паттерн Прокси
• Код должен, использующий базовый интерфейс для Заглушек и реальных объектов, должен удовлетворять принципу подстановки Лисков
• Тестируемые классы должны либо конфигурироваться интерфейсами, либо использовать фабрики
Mocks
Тестирование основанное на состояниях (традиционный подход)
Недостатки: – Требует знания о внутреннем состоянии объекта –возможно
нарушение инкапсуляции
– Нарушает принципы ООП
Тестирование основанное на поведении – сосредоточено на том, какие методы вызываются, в какой последовательности, какие результаты выдают
Поведенческое тестирование – тестирование того, как объект взаимодействует с другими объектами, то есть посылает выходные данные и принимает входные от других объектов.
Mock-объект – прокси-объект, который определяет прошел ли тестируемый объект тест или нет
Различие между Stub и Mock:
• Stub подменяет реальный объект с целью имитации реального функционала
• Mock подменяет реальный объект с целью оценки правильности взаимодействия тестируемого объекта с подменяемым.
Подходы к реализации mock
• Proxy (easymock, jmock, moq, rhino.mocks)
• Подгрузка класса mock объекта вместо реального класса
(jmockit, powermock, DI контейнеры)
Библиотека EasyMock
IFoo mock = EasyMock.createMock(IFoo.class);
EasyMock.expect(mock.doSomething(“argument”)).andReturn(true);
EasyMock.replay(mock);
bool result = test.perform();
EasyMock.verify(mock);
Проверка поведения метода
• andExpectThrow(exception)
• ExpectLastCall();
• times(min, max)
• AnyTimes()
• AtLeastOnce()
Параметры метода
• 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);
Пример теста
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);
}
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);
}
}
Библиотека 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);
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);
7. Возврат разных значений на каждый вызов функции
var mock = new Mock<IFoo>();
var calls = 0;
mock.Setup(foo => foo.GetCountThing())
.Returns(() => calls)
.Callback(() => calls++);
Console.WriteLine(mock.Object.GetCountThing());
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");
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");
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));
mock.Setup(foo => foo.Execute("ping"))
.Callback(() => Console.WriteLine("Before returns"))
.Returns(true)
.Callback(() => Console.WriteLine("After returns"));
Проверки 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());
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));
Пример: восстановление
пароля – шаг 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);
}
Пример: восстановление
пароля – шаг 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);
}
Пример: восстановление
пароля – шаг 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);
}
Пример: восстановление
пароля – шаг 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");
}
Пример: заглушка для еще
не написанного объекта
Interface IUserStorage
{
bool Save(User user);
bool Connect(string userName);
}
Пример: заглушка для еще
не написанного объекта
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);
}
Пример тестирования через
mock-объект
Пример 03.007.02-2011.01
Пример: модульное
тестирование
Пример 03.007.02-2011.03
Пример: отладка тестов
через mock-объекты
Пример 03.007.02-2011.02
Мок-объекты использованы для отладки самих тестов
Пример: нагрузочные тесты
Пример 03.007.02-2011.05
Идеи для применения mock
• Тестирование сложности алгоритмов
• Графический интерфейс
Пример: тестирование
пользовательского интерфейса
Puppeteer, Вальтер Антон (http://blogr.avalter.net/2009/06/puppeteer.html)
• АОП или использование aссessors
• Требует написания кода для обработки элементарных типов пользовательского интерфейса
[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; } }
public partial class Form1 : Form
{ // ............ [PuppetChild("TextBox")] [ReflectedPuppetProperty("Text","Text",typeof(SingleStringParamCreator))] private System.Windows.Forms.TextBox textBox1; // ............
}
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);
puppeteer.Run(new Dictionary<string, string>());
textBox1.Text = puppeteer.Result;
PuppetHolder.Clear();
Пример: тестирование
сложности алгоритмов
Пример 03.007.02-2011.04
LOGO hwdtech.com