Как был бы Вы модульный тест do_int_to_string_conversion?
#include <string>
#include <iostream>
void do_int_to_string_conversion(int i, std::string& s) {
switch(i) {
case 1:
s="1";
break;
case 2:
s="2";
break;
default:
s ="Nix";
}
}
int main(int argc, char** argv){
std::string little_s;
do_int_to_string_conversion(1, little_s);
do_int_to_string_conversion(2, little_s);
do_int_to_string_conversion(3, little_s);
}
Я предполагаю, что это просто пример. Почему вы не можете утверждать значение little_s после каждого вызова?
do_int_to_string_conversion(1, little_s);
assert_are_equal("1", little_s);
Вы можете использовать что-то вроде Expect, чтобы передать ему некоторые входные данные и проверить, что его выходные данные соответствуют тому, что должно быть.
Вместо того, чтобы беспокоиться о том, как протестировать функцию в ее нынешнем виде, я бы переделал функцию, чтобы она работала более разумно, и вместо этого протестировал бы переработанную версию.
Прямо сейчас у функции, похоже, есть три отдельных (и лишь немного связанных) обязанности: выполнить преобразование, изменить строку, предоставленную извне, и записать некоторые данные в поток. Поток, в который он записывает ( std :: cout
), также жестко запрограммирован - проблема, ожидающая своего появления (например, преобразование в среду графического интерфейса, вероятно, будет нетривиальным).
Я бы начал с 1) разделения его на логические функции и 2) предоставления потока в качестве параметра.
std::string convert_int(int val) {
switch (val) {
case 1: return "1";
case 2: return "2";
default: return "Nix";
}
}
std::ostream &write_string(std::ostream &os, std::string const &s) {
return os << s;
}
Я не включил ничего, чтобы (конкретно) изменить передаваемую извне строку - очевидно, вы можете присвоить возвращаемое значение из convert_int
, как считаете нужным, и значение строки, которая была передана в в любом случае не использовался.
По правде говоря, write_string
- хороший кандидат для полного исключения, но, поскольку у вас была такая базовая возможность, мы пока сохраним ее. Проверить их относительно просто - для convert_int
мы смотрим на строку, которую он возвращает, и сравниваем с ожидаемой. Для write_string
мы можем передать stringstream
вместо обычного ostream
- тогда мы можем использовать .str ()
, чтобы получить это результат в виде строки и (снова) сравнить с тем, что мы ожидаем.
Я бы изменил do_int_to_string_conversion
так, чтобы он выполнял только одно действие (преобразовывал in в строку).
void do_int_to_string_conversion(int i, std::string& s) {
switch(i) { ... }
}
Это не имеет побочных эффектов, поэтому вы можете написать простой модульный тест, который проверяет выходные данные.
Если бы мне понадобилась функция, выводящая результат преобразования, я бы поместил ее в отдельную функцию и параметризовал бы выходной поток.
void output_int(int i, ostream &stream) {
std::string s;
do_int_to_string_conversion(i, s);
stream << s;
}
Для модульного тестирования я бы передал объект std :: stringstream и проверил результат.
Если вам действительно нужно убедиться, что вывод был записан, вам нужно разорвать вашу зависимость от ] std :: cout
и использовать другой std :: ostream
во время тестов.
Это может быть так же просто, как глобальная переменная:
#if PRODUCTION
std::ostream my_output = std::cout;
#else
std::ostream my_output = std::ostringstream;
#endif
void setup()
{
my_output = std::ostringstream;
}
void print_hello()
{
my_output << "hello";
}
void test_hello_was_printed()
{
print_hello();
ASSERT("hello" == my_output.str());
}
Или что-то подобное с этим эффектом.