Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Otvety.docx

.pdf
Скачиваний:
45
Добавлен:
03.03.2016
Размер:
934.89 Кб
Скачать

Рис. 20.2. Постепенная интеграция модулей при нисходящем методе тестирования

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

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

6. Методология разработки приложения через тестирование.

Разработка через тестирование (англ. test­driven development) ​—

техника программирования, при которой модульные тесты для программы или её фрагмента пишутся до самой программы (англ. test­first development) и, по существу, управляют её разработкой.

1)разработка модульных тестов, которые не проходят (тесты обычно пишут таким образом, чтобы проверка функицонала была максимальна)

2)разработка функционален (аналогично с тестами, возможно написание не полного функционала, который удовлетворяет требованиям и проходит тест)

3)уточнение

// это из лекций и является основой, далее последует информация из интернета

Методика разработки через тестирование(Test­Driven Development, TDD) позволяет получить ответы на вопросы об организации автоматических тестов и выработке определенных навыков тестирования.

«Чистый код, который работает» ​­ в этой короткой, но содержательной фразе, кроется весь смысл методики разработки приложений через тестирование. Чистый код, который работает, ­ это цель, к которой стоит стремиться, и этому есть причины:

Это предсказуемый способ разработки программ. Разработчик знает, когда работу следует считать законченной, и можете не беспокоиться о длинной череде ошибок.

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

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

Разработчику приятнее писать такой код.

Однако как мы можем получить чистый код, который работает? Очень многие силы мешают нам добиться этого, а иногда нам не удается получить даже код, который работает. Чтобы избавиться от множества проблем, мы будем разрабатывать код, исходя из автоматических тестов. Такой стиль программирования называется разработкой через тестирование. В рамках этой методики мы:

Пишем новый код только тогда, когда автоматический код не сработал.

Удаляем дублирование.

Два столь простых правила на самом деле генерируют сложное индивидуальное и

групповое поведение со множеством технических последствий:

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

Мы самостоятельно пишем свои собственные тесты, так как мы не можем ждать, что кто­то другой напишет тесты для нас.

Наша среда разработки должна быстро реагировать на небольшие модификации кода.

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

кода упрощается.

Два упомянутых правила TDD определяют порядок этапов программирования:

1 Красный напишите небольшой тест, который не работает, а возможно, даже не компилируется.

2Зеленый заставьте тест работать как можно быстрее, при этом не думайте о правильности дизайна и чистоте кода. Напишите ровно столько кода, чтобы тест сработал.

3Рефакторинг удалите из написанного

вами кода любое дублирование.

Освоив TDD, разработчики обнаруживают, что они пишут значительно больше тестов, чем раньше, и двигаются вперед маленькими шагами, которые раньше могли показаться бессмысленными.

Заставив тест работать, мы знаем, что теперь тест работает , отныне и навеки. Мы стали на шаг ближе к завершению работы, чем мы были до того, как тест сработал. После этого мы заставляем второй тест работать, затем третий, четвертый и т.д. Чем сложнее проблема, стоящая перед программистом, тем меньшую область функциональности должен покрывать каждый тест.

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

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

7.Основные антипаттерны разработки тестов.

Анти­паттерны— полная противоположность паттернам. Если паттерны проектирования — это примеры практик хорошего программирования, то есть шаблоны решения

определённых задач. То анти­паттерны — их полная противоположность, это — шаблоны ошибок, которые совершаются при решении различных задач. Частью практик хорошего программирования является именно избежание анти­паттернов. Не надо думать, что это такая непонятная теоретическая фигня — это конкретные проблемы, с которыми сталкивался практически каждый разработчик. Кто осведомлен, тот и вооружён! Рассмотрим же несколько распространенных анти­паттернов в программировании.

Лжец (The Liar)

Unit­тест, который успешно выполняет все кейсы и выглядит работающим правильно, однако при более детальном рассмотрении обнаруживается, что он на самом деле не тестирует то, что должен.

Чрезмерная Инициализация (Excessive Setup)

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

единственного теста, создавая при этом множество объектов. Из­за этого «шума» сложно удостовериться что именно тестируется.

Гигант (Giant)

Unit­тест, который хотя и правильно тестирует приложение, но растекается на тысячи строк кода и содержит слишком много кейсов. Это может служить признаком того, что тестируемая система представляет из себя антипаттерн Всемогущий Объект (God Object).

Подделка (The Mockery)

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

Инспектор (The Inspector)

Unit­тест, который нарушает инкапсуляцию в попытке достичь 100% покрытия кода (code coverage) и при этом знает слишком много о тестируемой системе. При рефакторинге системы такой тест слишком часто ломается и требует исправлений.

Щедрые Остатки (Generous Leftovers)

Случай, когда один unit­тест создаёт данные, которые где­то сохраняются, а другой тест их потом переиспользует. Если «генератор данных» будет по какой­то причине вызван позже или пропущен, то тест, использующий его данные, не пройдёт.

Местный Герой (The Local Hero)

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

Крохобор (The Nitpicker)

Unit­тест, который проверяет весь результат работы, в то время как на самом деле важна только его малая часть. В результате приходится часто обновлять тест, чтобы отражать изменения в незначительных вещах. Типичен при тестировании веб­приложений.

Тайный Ловец (The Secret Catcher)

Тест, который на первый взгляд не делает никакого тестирования из­за отсутствия

assertions, но на самом деле дёргает за ниточки системы и полагается на выбрасывание какого­то исключения в случае проблем. Ожидается, что тестовое окружение поймает эту ошибку и отобразит тест как проваленный.

Уклонист (The Dodger)

Unit­тест, который тестирует множество второстепенных (и, как правило, простых) мелочей, но не тестирует основное поведение.

Крикун (The Loudmouth)

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

Жадный Ловец (The Greedy Catcher)

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

Любитель Порядка (The Sequencer)

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

Скрытая Зависимость (Hidden Dependency)

Близкий родственник Местного Героя. Это unit­тест, который требует, чтобы перед запуском были заполнены какие­то данные. Если эти данные отсутствуют, то тест падает, оставляя мало информации о причине проблемы и заставляя разработчика копаться в груде кода для того, чтобы определить какие данные и откуда должны были взяться.

Счётчик (The Enumerator)

Unit­тест, в котором все кейсы плохо именованы (например, test1, test2, test3). В результате назначение тест­кейса неясно и единственный способ понять, что сломалось — лезть в код теста и молиться, чтобы он оказался понятным.

Чужак (The Stranger)

Кейс, который не относится к unit­тесту, в котором он расположен. Он на самом деле тестирует совершенно другой объект, чаще всего объект, который используется основным тестируемым объектом. Также известен как Дальний Родственник.

Приверженец ОС (The Operating System Evangelist)

Unit­тест, который полагается на особенности определённой операционной системы. Хорошим примером будет тест, который ожидает перевода строки, принятого в Windows и ломающийся, когда выполняется под Linux.

Успех Любой Ценой (Success Against All Odds)

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

«Заяц» (The Free Ride)

Вместо того, чтобы написать новый кейс­метод, просто добавляется новый assert к существующему кейсу.

Избранный (The One)

Комбинация нескольких анти­паттернов, в особенности «Зайца» и Гиганта. Такой unit­тест состоит из единственного метода, который тестирует всю функциональность объета. Типичным индикатором проблемы являтся название тестового метода по названию unit­теста и большое количество строк инициализации и assert­ов.

Подглядыватель (The Peeping Tom)

Тест, который из­за общих ресурсов может видеть данные других тестов и может упасть, даже если тестируемая система полностью валидна. Типичным примером может служить использование статических полей для хранения коллекций. Если они не очищаются должным образом, то возможны неожиданные побочные эффекты в других тестах. Также известен как анти­паттерн Незваные Гости.

Тормоз (The Slow Poke)

Unit­тест, который выполняется крайне медленно. Когда разработчик запускает его, то у него появляется достаточно времени, чтобы сходить в туалет или покурить. Или, что может быть ещё хуже, он не станет дожидаться завершения тестирования перед тем, как вечером закоммититься и пойти домой.

8. Отладка. Классификация ошибок.

Классификация ошибок

Всоответствии с этапом обработки, на котором появляются ошибки, различают:

синтаксические ошибки­ ошибки, фиксируемые компилятором (транслятором, интерпретатором) при выполнении синтаксического и частично семантического анализа программы;

ошибки компоновки­ ошибки, обнаруженные компоновщиком (редактором связей) при объединении модулей программы;

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

Синтаксические ошибки

Синтаксические ошибки относят к группе самых простых, так как синтаксис языка, как правило, строго формализован, и ошибки сопровождаются развернутым комментарием с указанием ее местоположения. Определение причин таких ошибок, как правило, труда не составляет, и даже при нечетком знании правил языка за несколько прогонов удается удалить все ошибки данного типа. Следует иметь в виду, что чем лучше формализованы правила синтаксиса языка, тем больше ошибок из общего количества может обнаруживать компилятор и, соответственно, меньше ошибок будет обнаруживаться на следующих этапах. В связи с этим говорят о языках программирования с защищенным синтаксисом и с незащищенным синтаксисом. К первым, безусловно, можно отнести Pascal, имеющий очень простой и четко определенный синтаксис, хорошо проверяемый при компиляции программы, ко вторым ­ Си со всеми его модификациями. Чего стоит хотя бы возможность выполнения присваивания в условном операторе в Си, например:

if(c = n) x = 0;

В данном случае не проверяется равенство cи n, а выполняется

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

Ошибки компоновки

Ошибки компоновки, как следует из названия, связаны с проблемами, обнаруженными при разрешении внешних ссылок. Например, предусмотрено обращение к подпрограмме другого модуля, а при объединении модулей данная подпрограмма не найдена или не

стыкуются списки параметров. В большинстве случаев ошибки такого рода также удается быстро локализовать и устранить.

Ошибки выполнения

К самой непредсказуемой группе относятся ошибки выполнения. Прежде всего они могут иметь разную природу, и соответственно по­разному проявляться. Часть ошибок обнаруживается и документируется операционной системой. Выделяют четыре способа проявления таких ошибок:

появление сообщения об ошибке, зафиксированной схемами контроля выполнения машинных команд, например, переполнении разрядной сетки, ситуации "деление на ноль", нарушении адресации и т.п.;

появление сообщения об ошибке, обнаруженной операционной системой, например, нарушении защиты памяти, попытке записи на устройства, защищенные от записи, отсутствии файла с заданным именем и т.п.;

"зависание" компьютера, как простое, когда удается завершить программу без перезагрузки операционной системы, так и "тяжелое", когда для продолжения работы необходима перезагрузка;

несовпадение полученных результатов с ожидаемыми.

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

неверное определение исходных данных;

логические ошибки;

накопление погрешностей результатов вычислений.

ошибки многопользовательского доступа (с общим исп. Ресурсов)

ошибки в используемых инструментах или библиотеках.

Шаги локализации ошибки(Обнаружение ошибки):

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

Отключение модулей программы

Отладочная печать(Размещение в программе операторов вывода в консоль названий меток по которым можно отследить ход программы )

Отладчик

Отла́дка — этап разработки компьютерной программы, на котором обнаруживают, локализуют и устраняют ошибки.

Методы отладки программного обеспечения

Отладка программы в любом случае предполагает обдумывание и логическое осмысление всей имеющейся информации об ошибке. Большинство ошибок можно обнаружить по косвенным признакам посредством тщательного анализа текстов программ и результатов тестирования без получения дополнительной информации. При этом используют различные методы:

ручного тестирования;

индукции;

дедукции;

обратного прослеживания.

Метод ручного тестирования

Это ­ самый простой и естественный способ данной группы. При обнаружении ошибки необходимо выполнить тестируемую программу вручную, используя тестовый набор, при работе с которыми была обнаружена ошибка. Метод очень эффективен, но не применим для больших программ, программ со сложными вычислениями и в тех случаях, когда ошибка связана с неверным представлением программиста о выполнении некоторых операций. Данный метод часто используют как составную часть других методов отладки.

Метод индукции

Метод основан на тщательном анализе симптомов ошибки, которые могут проявляться как неверные результаты вычислений или как сообщение об ошибке. Если компьютер просто "зависает", то фрагмент проявления ошибки вычисляют, исходя из последних полученных результатов и действий пользователя. Полученную таким образом информацию организуют и тщательно изучают, просматривая соответствующий фрагмент программы. В результате этих действий выдвигают гипотезы об ошибках, каждую из которых проверяют. Если гипотеза верна, то детализируют информацию об ошибке, иначе ­ выдвигают другую гипотезу.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]