Введение
В этом лабораторном задании мы исследуем важность тестирования при разработке программного обеспечения на Rust и узнаем, как писать различные виды тестов, такие как модульные тесты и интеграционные тесты. Мы также узнаем, как организовать тесты в проектах на Rust и запускать их с помощью команды cargo test. Кроме того, мы обсудим возможные проблемы, которые могут возникнуть при параллельном запуске тестов, и приведем пример, иллюстрирующий это.
Примечание: Если в лабораторном задании не указано имя файла, вы можете использовать любое имя файла, которое хотите. Например, вы можете использовать
main.rs, скомпилировать и запустить его с помощьюrustc main.rs &&./main.
Тестирование
Как мы знаем, тестирование является неотъемлемой частью любого программного обеспечения! Rust имеет первоклассную поддержку для модульных и интеграционных тестов (см. этот раздел в TRPL).
Из разделов о тестировании, ссыланных выше, мы узнаем, как писать модульные и интеграционные тесты. Организационно мы можем размещать модульные тесты в модулях, которые они тестируют, а интеграционные тесты в собственной директории tests/:
foo
├── Cargo.toml
├── src
│ └── main.rs
│ └── lib.rs
└── tests
├── my_test.rs
└── my_other_test.rs
Каждый файл в tests является отдельным интеграционным тестом, то есть тестом, предназначенным для тестирования вашей библиотеки, как будто она вызывается из зависимой коробки.
Раздел о Тестировании подробно описывает три различных стиля тестирования: модульные, документационные и интеграционные.
cargo естественно предоставляет простой способ запустить все ваши тесты!
$ cargo test
Вы должны увидеть вывод в таком виде:
[object Object]
Вы также можете запустить тесты, чье имя соответствует шаблону:
$ cargo test test_foo
[object Object]
Одна важная вещь: Cargo может запускать несколько тестов одновременно, поэтому убедитесь, что они не конфликтуют друг с другом.
Одним примером, когда параллелизм вызывает проблемы, является ситуация, когда два теста выводят данные в файл, как ниже:
#[cfg(test)]
mod tests {
// Импортируем необходимые модули
use std::fs::OpenOptions;
use std::io::Write;
// Этот тест записывает данные в файл
#[test]
fn test_file() {
// Открывает файл ferris.txt или создает его, если он не существует.
let mut file = OpenOptions::new()
.append(true)
.create(true)
.open("ferris.txt")
.expect("Failed to open ferris.txt");
// Печатает "Ferris" 5 раз.
for _ in 0..5 {
file.write_all("Ferris\n".as_bytes())
.expect("Could not write to ferris.txt");
}
}
// Этот тест пытается записать данные в тот же файл
#[test]
fn test_file_also() {
// Открывает файл ferris.txt или создает его, если он не существует.
let mut file = OpenOptions::new()
.append(true)
.create(true)
.open("ferris.txt")
.expect("Failed to open ferris.txt");
// Печатает "Corro" 5 раз.
for _ in 0..5 {
file.write_all("Corro\n".as_bytes())
.expect("Could not write to ferris.txt");
}
}
}
Хотя ожидаемый результат следующий:
$ cat ferris.txt
Ferris
Ferris
Ferris
Ferris
Ferris
Corro
Corro
Corro
Corro
Corro
В самом файле ferris.txt на самом деле находится следующее:
$ cargo test test_foo
Corro
Ferris
Corro
Ferris
Corro
Ferris
Corro
Ferris
Corro
Ferris
Резюме
Поздравляем! Вы завершили лабораторную работу по Тестированию. Вы можете практиковаться в других лабораторных работах в LabEx, чтобы улучшить свои навыки.