Написання автоматизованих тестів

У 1972 році у своєму есе "Скромний програміст" Едсгер Дейкстра сказав “Тестування програми може бути дуже ефективним способом показати наявність помилок, але його зовсім недостатньо, щоб показати їх відсутність.” Це не означає, що ми не повинні тестувати стільки, скільки ми можемо!

Коректність наших програм полягає у ступені відповідності того, що вони роблять тому, що ми мали на увазі, коли їх розробляли. Rust розроблений з високим ступенем турботи про коректність програм, але коректність є складною та її не легко довести. Система типів Rust несе величезну частину цього тягаря, але вона не здатна впоратися з усім. Таким чином, Rust включає підтримку написання автоматизованих тестів програмного забезпечення.

Нехай ми пишемо функцію add_two яка додає 2 до будь-якого числа, що передано в неї. В сигнатурі цієї функції ми вказуємо ціле число як вхідний параметр, та ціле число, як результат, що повертається. Коли ми реалізуємо та компілюємо цю функцію, Rust робить усі перевірки типів та запозичень, щоб гарантувати, що ми не передаємо String або недійсне посилання до цієї функції. Але Rust не може перевірити, що ця функція робить безпосередньо те, що ми задумали, що повертає параметр плюс 2, а не, скажімо, параметр плюс 10 або параметр мінус 50! Ось тут і з'являються тести.

Ми можемо написати тести, які підтверджують, що, наприклад, коли ми передаємо 3 до функції add_two, то вона повертає значення 5. Ми можемо запускати ці тести кожного разу, коли вносимо зміни до нашого коду, щоб бути впевненими в тому, що коректна поведінка програми при цьому не змінилася.

Тестування - це складна навичка: хоча ми не можемо в одному розділі охопити усі нюанси того, як створювати гарні тести, ми оглянемо засоби тестування у Rust. Ми поговоримо про анотації та макроси, доступні вам для написання тестів, про поведінку за замовчуванням та параметри для запуску ваших тестів, а також як організувати тестування за допомогою unit- та інтеграційних тестів.