Информация из этой статьи явно пригодится вам, если вы планируете или уже участвуете в соревнованиях, олимпиадах из перечня РСОШ или ВСОШ по предмету информатика (программирование).
Я расскажу о самых популярных и удобных способах тестирования, которые должен знать каждый, а также дам пару практических советов о том, что делать, когда вердикт вашего решения WA (wrong answer) или TL (time limit).
Методы тестирования
1. Стресс-тесты
Основная идея – сравнение ответов, которые выдает ваше решение и медленная реализация, в то время как входные данные подбираются случайным образом.
Такой способ используется, когда:
-
Входные данные легко генерируются.
-
Медленное решение существует и пишется относительно недолго.
-
Ваша цель — найти тест, где программа получает неверный ответ или вовсе происходит ошибка выполнения.
У такого вида тестирования есть достаточно много реализаций. Кто-то пишет специальные скрипты, но на олимпиадах актуальнее и проще всего использовать обычные функции. Вот пример на языке Python:
import random
def my_solution(k: int):
answer = k // 2
return answer
def slow_solution(k: int):
answer = 0
for i in range(0, k + 1):
if i % 2 == 0:
answer += 1
return answer
for i in range(100):
n = random.randint(1, 100)
if my_solution(n)!= slow_solution(n):
print(n)
Как медленное решение советую использовать перебор, несмотря на то, что решение работает за O (n) или вообще O (n²), но главное — оно будет заведомо верное.
В каждом языке есть свои предустановленные модули для хаотичного получения значений:
# в Python
import random
n = random.randint(a, b)
// в C++
#include <iostream>; #include <cstdlib>; #include <ctime>
using namespace std;
int main() {
int a = 0; int b = 10;
int n = a + rand() % (b - a + 1);
cout << n << endl;
return 0;
}
2. Встроенные дебаггеры
В каждой среде разработки есть возможность выполнять программу построчно. В классической реализации вам предоставляется возможность поставить точки останова — это значит, что в определённый момент программа прервётся и вы сможете просматривать значение переменных, входить/выходить из циклов, видеть всё поведение в общем.
На практике использовать дебаггер полезно, когда:
-
Есть тест с непонятным поведением программы.
-
Ваше решение объёмное — в нём с ходу не найти ошибку (часто, если это полный перебор, рекурсия или любой другой сложный алгоритм).
-
В запасе есть достаточно времени — так как вам нужно будет проверить каждый шаг программы.
Подробнее почитать про особенности дебаггеров в разных средах советую здесь:
По ссылкам вы найдете официальную документацию с подробным описанием различных особенностей.
3. Проверка граничных случаев
Нередко, ошибки в решении связаны со специфическими случаями. Вот целый список подобных ситуаций:
-
Переполнение – встречается при работе с большими числами в некоторых языках программирования (С++ и т.д.)
-
Превышение глубины рекурсии – ее надо либо увеличивать (как в Python) или менять решение
-
Нехватка памяти – часто бывает, если вы создаете большой массив или храните объемные данные
-
Необработанные граничные случаи – например программа не выводит -1 или не обрабатывает часть входных данных
-
Нестабильное поведение при работе с отрицательными числами -следовательно, найденное вами решение некорректно
-
Деление на 0 или неправильная работа с вещественными числами: их сравнение, деление, округление, потеря точности
Чтобы избежать все эти ошибки и исправить их на начальной стадии стоит:
-
Запустить свое решение на минимальных значениях
-
Повторить то же самое с максимальными значениями
-
Если это удовлетворяет условиям сделать тесты с отрицательными числами отрицательными и положительными
-
Придумать тесты на другие граничные случаи исходя из условий
К этому методу стоит прибегнуть, если ваше решение не проходит лишь маленькое количество тестов. Или же, при наличии желания, можно протестировать таким образом программу перед отправкой, чтобы убедиться в корректности работы. Это не займет много времени, если вы потренируетесь придумывать тесты.
4. Дополнительные советы
Перед тем как начинать тестировать решение никогда не будет лишним перечитать условия, у меня часто бывает, что в какой-то момент я начинаю решать абсолютно другую задачу. Иногда она оказывается проще, иногда труднее, но в любом случае, никому такого не пожелаю!
Также не стоит забывать, что простые методы тестирования никуда от нас не уходят. Вывод отдельных значений, тесты, подобранные собственноручно. Часто этого предостаточно особенно в нетрудных задачах. Скорее всего, не стоит сразу бежать писать стресс-тесты или дебажить весь алгоритм от начала до конца.
Возможно, кому-то все эти способы и покажутся банальными. Я же использую все эти методы регулярно, каждый из них хорош по-своему. Если у вас есть свои любимые способы тестирования, которыми вы готовы поделиться, то обязательно пишите в комментариях, мне уже не терпится о них узнать!
Автор: mdanilova
