Rust: с нуля до своего органайзера Урок 16 из 20
Первый автоматический тест
Урок 16. Проверить расчёт функцией, которая сама сообщает о неверном результате.
Текст переведён с помощью ИИ.
Предварительно: уроки 1–15, особенно функции и массивы. Цель — поймать ошибку в функции до использования сводки. Пока тестируем числа, без новых библиотек.
Образ и опорная карта
Ручная проверка похожа на повторное взвешивание одной посылки. Автоматический тест — сохранённое правило «для такого входа ожидаю такой результат», которое можно запускать после каждого изменения. Оно проверяет выбранные случаи, а не доказывает правильность всех возможных входов.
Вход → функция → фактический результат ↔ ожидаемый результат → сообщение теста. Воспроизведите эту цепочку по памяти, прежде чем смотреть код.
Подготовка и первый запуск
Заранее разберём два новых обозначения. #[test] — атрибут, метка перед функцией без аргументов. # начинает метку, квадратные скобки содержат её имя, а test означает «запустить следующую функцию как тест». assert_eq!(фактическое, ожидаемое) — макрос сравнения: первый аргумент вычисляется кодом, второй задаём мы. ! обозначает макрос, как в println!. При равенстве проверка проходит; при неравенстве показывает оба значения и проваливается.
В проекте organizer из урока 6, в папке с Cargo.toml, сохраните прежний src/main.rs отдельно и замените его целиком кодом ниже. Другие файлы не меняем. cargo run собирает и запускает обычную программу; cargo test собирает и запускает функции с атрибутом #[test]. Обе команды вводятся в терминале проекта. Вывод ниже относится только к cargo run; сообщения тестового запуска могут отличаться по версии инструмента.
fn remaining(total: u32, done: u32) -> u32 {
total - done
}
fn main() {
println!("Осталось: {}", remaining(7, 2));
}
#[test]
fn subtracts_done_tasks() {
assert_eq!(remaining(7, 2), 5);
}
Осталось: 5
cargo test найдёт функцию по метке; main её не вызывает. Тест находится в том же файле и может вызвать remaining, объявленную выше. Группировать тесты в отдельный модуль научимся в уроке 44.
assert_eq! ничего не печатает при успехе. cargo test должен сообщить 1 passed; 0 failed; остальные строки зависят от версии Cargo. Тест не исправляет функцию сам.
Намеренно сломайте и восстановите
Поменяйте в тесте ожидаемое 5 на 6 и выполните cargo test: тест должен провалиться. Верните 5. Затем поменяйте реализацию на total + done: снова получите провал. Верните вычитание. Если done > total, вычитание u32 нарушает предусловие урока 14; эта функция предназначена только для done <= total. Обработку неверного ввода добавим после Result.
Проверьте себя
Что запускает cargo run, а что — cargo test? Может ли один успешный тест доказать, что функция верна для любого u32? Ответ: первый запускает main, второй — тестовые функции; нет. Попробуйте ответить без карты.
Задание
Обязательное. Напишите функцию is_short(minutes: u32) -> bool по правилу урока 14: от 1 до 15 включительно. Добавьте три теста: 0 → false, 15 → true, 16 → false. Сначала запишите ожидаемые результаты, затем выполните cargo test. Обычная программа должна вывести Короткая: true для 15. Измените один ожидаемый результат, убедитесь в провале и верните его. Если забыли синтаксис условия, вернитесь к уроку 11.
Подсказка
Каждая проверка — отдельная функция с #[test] в том же файле, после main. Сравнивайте результат is_short(...) с true или false.
Эталон после попытки
fn is_short(minutes: u32) -> bool {
minutes > 0 && minutes <= 15
}
fn main() {
println!("Короткая: {}", is_short(15));
}
#[test]
fn zero_is_not_a_task() {
assert_eq!(is_short(0), false);
}
#[test]
fn fifteen_is_short() {
assert_eq!(is_short(15), true);
}
#[test]
fn sixteen_is_long() {
assert_eq!(is_short(16), false);
}
Короткая: true
Эталон показывает три разные границы, поскольку один пример с 15 не обнаружил бы принятие нуля или 16. Справка по тестам Rust.
Если вы нашли ошибку или опечатку в тексте статьи, то сообщите нам об этом
Комментарии (0)
Войдите, чтобы оставить комментарий →
Пока нет комментариев. Будьте первым.