maran program engineering (830029), страница 27
Текст из файла (страница 27)
При этом надо предусмотреть и случаи, когдаисходные данные отсутствуют или их количество превышает максимально допустимое.• Составление тестов таким образом, чтобы все классы были покрыты тестами, но их общее количество было минимальным.Проиллюстрируем сказанное на простом примере. Дан массив. Найти суммуего элементов, удовлетворяющих условию c1<=x<=c2. Исходные данные: с1,с2 и массив. Могут быть заданы пределы, в которых элементы массива должнынаходиться, допустим, от xmin до xmax.163Классы эквивалентности для xmin до xmax, xmin <= xmax.
При xmin=xmaxзадача бессмысленна. В принципе можно в программе поменять их местами.Классы эквивалентности для с1, с2:Правильный класс эквивалентности: xmin<=c1; c1<=c2; c2<=xmax. Задача может быть решена без проблем.Неправильные классы эквивалентности: c2<c1; c1 или c2 меньше xmin; c1или c2 больше xmax. В принципе все названные случаи можно решить и алгоритмически в тестируемой программе: значения границ меньше или большедопустимых заменить на соответствующие крайние значения.
Если c2<c1, топоменять их местами. Но реакции программы на все эти случаи должны бытьпроверены.Классы эквивалентности массива.При правильных значениях с1 и с2 проверить принадлежность элементовзаданного массива допустимому интервалу смысла не имеет: элементы, значениями за допустимыми пределами, на результат не влияют. Если массив введенне только для решения этой задачи, то такая проверка необходима. Классы эквивалентности:1.
xi<c1 ответ — сумму найти невозможно.2. xi>c2 ответ — сумму найти невозможно.3. c1<= xi<=c2 сумма, при вычислении учтены только удовлетворяющие условию.В специфике программы должно быть задано, какие исходные данныетребуются и каким ограничениям их значения должны удовлетворять. Допустим, в тестируемой программе xmin и xmax заданы константами, требуется ввести с1 и с2, количество элементов N и сами элементы. Тогда минимальное покрытие выделенных классов эквивалентности:1.
с1<c2, N=0.2. c1<c2, N>0, имеются элементы xi<c1 и элементы xi>c2, но нет элементовс1<= xi<=c2.3. c1<c2, N>0, имеются элементы, как принадлежащие интервалу, так и непринадлежащие.4. с1>c2, N=0.5. с1>c2, N>0, имеются элементы xi<c1 и элементы xi>c2, но нет элементовс1<= xi<=c2.6. с1>c2,N>0, имеются элементы, как принадлежащие интервалу, так и непринадлежащие.Крайне маловероятно на практике, что все решение содержится в однойглавной функции (столь простых задач не бывает!), поэтому как продолжениеначатого примера рассмотрим для случая, когда задача решена в виде функциидля дальнейшего использования в составе более крупной программы.
Пустьформальными параметрами функции являются исходный массив, границы диапазона с1 и с2 и сигнальная переменная. Функция не выполняет проверку принадлежности элементов массива допустимому интервалу, считаем, что эта задача, в случае необходимости, решена в вызывающей программе. Сигнальная164переменная свидетельствует о случаях, когда получение ответа невозможно.Реализация функции:static double Sum1(double[] mas, double c1, double c2, out int sig){ // sig – сигнальная переменнаяdouble temp;if (mas == null){// Проверка случая, когда массиву// не соответствует указательsig = 1;return 0;}if (mas.Length==0 ){ // Массив инициирован, но в нем нет элементовsig = 1;return 0;}}sig = 2;// Массив задан, но в нем нет искомых элементовif(c1>c2){temp=c2; c2=c1;c1=temp;temp = 0;for (int i = 0; i < mas.Length; i++){if (c1 <= mas[i] && mas[i] <= c2){}temp += mas[i];sig = 0; //Найден хотя бы один элемент}return temp;}Ниже приведена вспомогательная главная функция для тестирования.
Такая функция называется драйвером, ее задача: вызывать тестируемую функциюс разными тестами и помогать тестировщику анализировать результаты.К драйверам мы еще вернемся при обсуждении тестирования программныхкомплексов. Желательно исходные данные для тестов не вводить, а присваивать в самой программе. За исключением случаев, когда их количество большое, в таком случае можно для их хранения использовать файлы.
Такой подход165позволяет легко выполнять одну из важнейших рекомендации проведения тестирования: учет использованных тестов.Пример функции-драйвера:static void Main(string[] args){int kp;double res;//Test1/*double[] arr = new double[0];res=Sum1(arr, 10, 20, out kp);*///Test 2/*double[] arr = {-1.2,3.5,9.9,20.1,43 };res = Sum1(arr, 10, 20, out kp);*/// Test 3/*double []arr={1.2,5.6,9.9,10.0,10.1,13.4,19.9,20,20.1,22.5};res = Sum1(arr, 10, 20, out kp);*///Test4/*double[] arr = new double[0];res=Sum1(arr, 20, 10, out kp);*///Test 5/*double[] arr = {-1.2,3.5,9.9,20.1,43 };res = Sum1(arr, 20, 10, out kp);*///Test 6/*double[] arr = { 1.2, 5.6, 9.9,10.0, 10.1, 13.4, 19.9, 20, 20.1, 22.5 };res = Sum1(arr, 20, 10, out kp);*/// Test7double[] arr = null;/* Случай скорее всего теоретический, использованиефактического параметра без начального значения166синтаксическая ошибка*/res = Sum1(arr, 10, 20, out kp);//---------- Вывод результатаif(kp==0)Console.WriteLine("Sum=" + res.ToString("F1"));if(kp==2)Console.WriteLine("Нет искомых элементов");if(kp==1)Console.WriteLine("Массив пуст");Console.ReadLine(); } }В случаях 1 и 4 должно выдаваться сообщение об отсутствии элементов,эти случаи можно не разделять.
Случаи, когда с1>c2, программа могла бы правильно отработать без выдачи сообщения. В случаях 2 и 5 должен появитьсяответ о невозможности вычисления суммы. В случаях 3 и 6 должна выдаватьсясумма, в которой учтены нужные элементы и не учтены ненужные. Хорошийтон программирования требует, чтобы ответ был понятен пользователю без дополнительных умозаключений. Поэтому ответ нуль для 3 и 6 следует считатьнеудачным.
Действительно, если c1>0 и c2>c1 ответ нуль означает отсутствиенужных элементов, но от пользователя требуются дополнительные рассуждения. При c1<0 и c2>0 ответ действительно может быть равен нулю.В нашем случае исходные данные (с1, с2 и массив) независимы, поэтомумы могли проанализировать их в отдельности. В общем случае допустимые инедопустимые классы эквивалентности могут возникнуть и на их сочетаниях(20-летний человек никак не может иметь трудовой стаж 25 лет). Пусть средиисходных данных имеются переменные x и y. Пусть 0<=x<=10 и 25<=y<=50,но должны соблюдаться ограничения x*y<=450 и x+y>30.Рекомендации:1.
Проанализировать вопрос: какие исходные данные независимы друг отдруг и между которыми имеется зависимость?2. Какие классы эквивалентности (как правильные, так и неправильные)возникают на сочетаниях классов эквивалентности разных данных?Метод граничных значений. Этот метод требует использовать в качестве тестов значения на границах и около границ классов эквивалентности. Еслиимеем дело с целыми числами, то понятно, что понимать под «около границы».При вещественных данных можно рассуждать так. Любая реально существующая величина измеряется и поступает на обработку в программу с какой-тоточностью, например 2 знака после запятой.
Тогда под «около» можно понимать ±0,001. Для рассмотренной выше задачи о сумме элементов в заданноминтервале среди них в тесте можно рекомендовать с1-∆, с1, с1+∆, . . . с2-∆, с2,с2+∆. О том, как выбирать ∆, мы только что поговорили.Для уменьшения количества тестов рекомендуют использовать эти дваметода совместно: сначала составить тесты по эквивалентному разбиению, а затем подкорректировать их таким образом, чтобы соблюдались рекомендациивторого метода.
В нашем примере можно рекомендовать следующие:1671. с1=10, с2=20; х: 1, 3.4, 9.99, 10, 10.1,…..19.9, 20,20.1, 22, . . .2. с1=10, с2=20; х:1, 3.4, 9.99,20.1, 22, . .В качестве упражнения рекомендуем читателю разработать тесты дляследующих задач.1. Решение квадратного уравнения ax2 + bx + c = 0.
Какие тесты необходимы, чтобы программа обрабатывала все (!) случаи и выдала либо ответ, либо сообщение о невозможности решения?2. Дано 3 числа. Могут ли они быть сторонами треугольника, а если да —то какого: тупоугольного, прямоугольного или остроугольного?3. И очень сложная задача. Дана дата: день — месяц — год. Допустим,что она корректная, т. е. такая дата действительно существует. Заданоцелое число М (возможно отрицательное). Какая дата будет через Мдней (при М> 0) или была М дней назад (при М< 0)? Для начала возьмите ограничение |М|<=365.6.2.2. Тестирование «белого ящика»Введем понятие «граф управления программой».
В любой программеприсутствуют три базовых конструкции: последовательность, выбор и повторение (цикл). Последовательности в графе управления можно ставить в соответствие одну вершину или столько вершин, сколько действий имеется в последовательности. Как мы скоро увидим, это ни на что не влияет. Разветвлению ставим в соответствие столько вершин, сколько элементарных условий в нем имеется.
Элементарным называем условие вида переменная — знак отношения —переменная, перед отношением может быть знак отрицания (вместо одной переменной может быть константа). Например, x>=5,4. Сложное условие получается путем соединения элементарных условий знаками операции И, ИЛИ.Например, (5,4<=x)&&(x<=9,3).Пример 1. Последовательность.Пусть имеем отрывок программы:K=3;X=2.5;Y=K*X.Его граф управления (рис.
6.2):.K=3X=2,5Y=K*XРис. 6.2Цикломатическая сложность программы определяется по формулеКоличество_ребер — количество_вершин + 2, в нашем случае 2 – 3+2=1. Нетрудно заметить, что добавление новых операторов в последовательность неменяет цикломатическую сложность. Другими словами, цикломатическаясложность последовательности всегда равна единице. Поэтому можно при со168ставлении графа управления программой последовательность представить одной вершиной. Интерпретация: цикломатическая сложность — это количествопутей от первой вершины до последней.Пример 2.