Skip to content

Commit 47c53f1

Browse files
committed
man QA. Классы эквивалентности и анализ граничных значений
1 parent 300436f commit 47c53f1

File tree

8 files changed

+173
-0
lines changed

8 files changed

+173
-0
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Классы эквивалентности и граничные значения
2+
3+
Выделение =классов эквивалентности= и анализ =граничных значений= -- два базовых взаимно-дополняющих друг друга подхода для тестирования программ.
4+
5+
> **Задача 1:**
6+
Подготовить тестове данные для проверки правильности работы программы вычисления модуля целого числа. На вход программе поступает произвольное значение типа `int`.
7+
8+
Листинг 1. Программа my_abs.c v.0.1
9+
```c
10+
#include <stdio.h>
11+
12+
int main(void)
13+
{
14+
int x, abs_x;
15+
scanf("%d", &x);
16+
17+
abs_x = x * (x < 0) * -1;
18+
printf("%d\n", abs_x);
19+
20+
return 0;
21+
}
22+
```
23+
24+
25+
## Выделение классов эквивалентности
26+
27+
Суть подхода заключается в том, что все возможные входные данные для программы разбиваются на отдельные группы (классы эквивалентности). Но разбиение на группы происходит не произвольным образом, а так, чтобы элементы одной группы обрабатывались в программе одинаково.
28+
29+
В нашем примере таких класса всего два:
30+
31+
- Отрицательные числа (например, `−5`, `−100`, `−2048`)
32+
- Положительные числа и нуль (например, `2`, `128`, `5000`)
33+
34+
Т.е. в работе программы можно выделить два возможных сценария:
35+
36+
**Сценарий 1:** Получили отрицательное число. Надо вернуть число с противоположным знаком.
37+
**Сценарий 2:** Получили положительное число или нуль. Надо вернуть число без изменений.
38+
39+
40+
Это позволяет систематизировать и упростить подготовку тестовых данных.
41+
42+
Вместо того, чтобы тестировать программу на различных случайных числах, мы выбираем из каждого класса по одному значению (представителю) и полагаем, что если для него программа работает корректно, то и для любого другого значения из этого же класса программа будет работать правильно.
43+
44+
С учётом сказанного, получаем первую версию тестовых данных:
45+
46+
```
47+
Тест 1: −10
48+
Тест 2: 25
49+
```
50+
51+
Собственно, уже даже этих тестов хватит, чтобы выявить проблему в нашей программе:
52+
53+
![](./my_abs_test_1.png)
54+
55+
Исправим нашу программу:
56+
57+
Листинг 1. Программа my_abs.c v.0.2
58+
```c
59+
#include <stdio.h>
60+
61+
int main(void)
62+
{
63+
int x, abs_x;
64+
scanf("%d", &x);
65+
66+
if (x < 0) {
67+
abs_x = -x;
68+
/* привет всем,
69+
кто надеялся списать решение
70+
https://stepik.org/lesson/57210/step/12
71+
*/
72+
}
73+
74+
printf("%d\n", abs_x);
75+
76+
return 0;
77+
}
78+
```
79+
80+
Теперь программа будет корректно работать на первом наборе тестовых данных.
81+
82+
83+
### Анализ граничных значений
84+
85+
Ошибки в программах очень часто возникают на границах между классами эквивалентности. Поэтому, помимо представителей классов стоит протестировать значения на самой границе и рядом с ней.
86+
87+
Очевидная граница для нашей задачи -- это значение `0`.
88+
89+
Дополним тестовые данные значениями `0`, `1` и `-1` и проверим работу программы Листинг 2 на новом наборе тестовых данных:
90+
91+
```
92+
// Справа от теста указан результат проверки
93+
94+
Тест 1: −10 OK!
95+
Тест 2: 25 OK!
96+
Тест 3: 0 OK!
97+
Тест 4: −1 OK!
98+
Тест 5: 1 OK!
99+
```
100+
101+
Чуть менее очевидными являются крайние значения, связанные с ограниченным объёмом типа `int`.
102+
103+
В моём компиляторе тип `int` занимает `4` байта, а потом минимальное и максимальное значения будут равны `-2147483648` и `2147483647`, соответственно.
104+
105+
Значит надо дополнить наш набор тестов значениями:
106+
`-2147483648`, `-2147483647`, `2147483647`, `2147483646`.
107+
108+
Значения `-2147483649` и `2147483648`, находящиеся с другой стороны границ, включать не требуется, т.к. по условию задачи на вход программе поступают лишь значения типа `int`.
109+
110+
111+
Дополните тестовый набор указанными значениями и снова запустим проверку программы:
112+
113+
```
114+
// Справа от теста указан результат проверки
115+
116+
Тест 1: −10 OK!
117+
Тест 2: 25 OK!
118+
Тест 3: 0 OK!
119+
Тест 4: −1 OK!
120+
Тест 5: 1 OK!
121+
Тест 6: -2147483648 BAD!
122+
Тест 7: -2147483647 OK!
123+
Тест 8: 2147483647 OK!
124+
Тест 9: 2147483646 OK!
125+
```
126+
127+
Результат работы программ Листинг 2 на шестом тесте:
128+
![](./my_abs_test_2.png)
129+
130+
В рамках типа `int` исправить эту проблему не получится, т.к. число `2147483648` превосходит максимальное значение (`INT_MAX` из заголовочного файла `limits.h`), которое может храниться в переменной типа `int`. Поэтому этот случай придётся признать исключительным и аварийно завершить программу:
131+
132+
Листинг 3. Программа my_abs.c v.1.0
133+
```c
134+
#include <stdio.h>
135+
#include <limits.h>
136+
137+
int main(void)
138+
{
139+
int x, abs_x;
140+
scanf("%d", &x);
141+
142+
if (x == INT_MIN)
143+
return 1;
144+
145+
if (x < 0)
146+
abs_x = -x;
147+
148+
printf("%d\n", abs_x);
149+
150+
return 0;
151+
}
152+
```
153+
154+
Вместо значения `INT_MIN`, можно, конечно, явно указать значение `-2147483648`, но тогда получился бы код, который жёстко привязан к размеру типа `int` в моей системе. Если же мы используем `INT_MIN`, то программа будет подстраиваться под тот размер `int`, который используется в системе, где компилируется программа.
155+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"title": "Классы эквивалентности и граничные значения",
3+
"description": "Учимся использовать классы эквивалентности и анализ граничных значений для эффективного тестирования программ. Подробный разбор с примерами и кодом на C для проверки правильности работы программы вычисления модуля целого числа",
4+
"keywords": "классы эквивалентности, граничные значения, тестирование программ, тестовые сценарии, тестирование программ на Си, модуль целого числа",
5+
"canonical_link": "https://youngcoder.ru/manuals/3/qa_equivalence_classes"
6+
}
12 KB
Loading
15.1 KB
Loading
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
## Практика
2+
**1.** Используя набор тестов, составленных на уроке, протестируйте работу библиотечной функции `abs(x)`.

manuals/3/0__qa_equivalence_classes/reference.md

Whitespace-only changes.

manuals/3/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Тестирование программ
2+
3+
Сборник заметок, посвящённых основам тестирования программ на языке Си.

manuals/3/meta.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"title": "Тестирование программ",
3+
"description": "В этом уроке собраные различные материалы по тестированию программ на языке Си.",
4+
"keywords": "тестирование ПО, тестирование программ, тестирование программ на Си",
5+
"canonical_link": "https://youngcoder.ru/manuals/3/",
6+
"has_glory_hall": false
7+
}

0 commit comments

Comments
 (0)