Какой лучший способ для больших наборов данных unit test? Некоторые устаревшие коды, которые я поддерживаю, имеют структуры из ста членов или более; другие части кода, которые мы работаем над созданием или анализом наборов данных из сотен образцов.
Лучший подход, который я нашел до сих пор, - это сериализовать структуры или наборы данных с диска, выполнить тестируемые операции, сериализовать результаты на диск, а затем разбить файлы, содержащие сериализованные результаты, на файлы, содержащие ожидаемые результаты. Это не очень быстро, и это нарушает принцип модульного тестирования "не касайтесь диска". Однако единственная альтернатива, которую я могу придумать (написать код для инициализации и тестирования сотен членов и точек данных), кажется невыносимо утомительной.
Есть ли лучшие решения?
Ответ 1
Если вы пытаетесь достичь, на самом деле, unit test вы должны издеваться над базовыми структурами данных и имитировать данные. Этот метод дает вам полный контроль над входами. Например, каждый написанный вами тест может обрабатывать одну точку данных, и у вас будет очень сжатый набор тестов для каждого условия. Есть несколько открытых систем с открытым исходным кодом, я лично рекомендую Rhino Mocks (http://ayende.com/projects/rhino-mocks/downloads.aspx) или NMock (http://www.nmock.org).
Если вы не можете издеваться над структурами данных, я рекомендую рефакторинг, чтобы вы могли:-) Его стоит! Или вы также можете попробовать TypeMock (http://www.typemock.com/), который позволяет насмехаться над конкретными классами.
Если, однако, если вы проводите тесты против больших наборов данных, вы действительно выполняете функциональные тесты, а не модульные тесты. В этом случае загрузка данных в базу данных или с диска является типичной операцией. Вместо того, чтобы избегать этого, вы должны работать над тем, чтобы он работал параллельно с остальной частью процесса автоматической сборки, поэтому влияние производительности не удерживает ни одного из ваших разработчиков.
Ответ 2
Это по-прежнему жизнеспособный подход. Хотя, я бы классифицировал это как функциональный тест или просто не чистый unit test. Хорошим unit test будет выборка из тех записей, которая дает хорошее распределение случаев кросс, с которыми вы можете столкнуться, и записывать их. Затем у вас есть ваш последний "прием" или "функциональный" тест с вашим массовым тестом на все данные.
Я использую этот подход при тестировании больших объемов данных, и я считаю, что он работает достаточно хорошо, потому что небольшие единицы поддерживаются, а затем я знаю, что массовый тест работает, и все это автоматически.
Ответ 3
Лучший подход, который я нашел до сих пор, - это сериализовать структуры или наборы данных с диска, выполнить тестируемые операции, сериализовать результаты на диск, а затем разбить файлы, содержащие сериализованные результаты, на файлы, содержащие ожидаемые результаты.
Я написал код, который использует вышеупомянутую технику, вместо того, чтобы сериализовать с диска в тесте, я преобразовал сериализованные данные в массив байтов, который компилятор может разместить в исполняемом файле для вас.
Например, ваши сериализованные данные могут быть преобразованы в:
unsigned char mySerialisedData[] = { 0xFF, 0xFF, 0xFF, 0xFF, ... };
test()
{
MyStruct* s = (MyStruct*) mySerialisedData;
}
Для более подробного примера (в С#) см. этот unit test. В нем показан пример использования некоторых жестко закодированных сериализованных данных в качестве входных данных для тестов, подписание тестовой сборки.