Я никогда раньше не писал модульные тесты по разным причинам. Теперь у меня есть возможность писать тесты с комфортом, потому что мне нужно сделать небольшое приложение с нуля.
Однако я немного озадачен. Приложение должно использовать принтер со считывателем смарт-карт для программирования данных на смарт-карте. Итак, вот последовательность действий: создать контекст устройства, установить режим принтера, инициализировать документ, подать карту в принтер, подключиться к карте с помощью считывателя, записать что-то на карту, вынуть карту, завершить документ, избавиться от контекст устройства.
Хорошо, предполагается, что модульные тесты проверяют одну функцию для каждого теста, и каждый тест должен выполняться независимо от результатов других тестов. Но давайте посмотрим - я не могу протестировать запись на смарт-карту, если неправильно расположил ее в принтере и не подключился к ней. И я не могу издеваться над этим с помощью программного обеспечения - я могу только проверить, действительно ли запись произошла, если реальная карта правильно расположена и подключена. А если подключиться к карте не получится, то нет возможности протестировать запись на карту - значит принцип независимости теста нарушен.
До сих пор я придумал такой тест (есть и другие тесты, которые являются «правильными» и проверяют и другие вещи)
[Test]
public void _WriteToSmartCard()
{
//start print job
printer = new DataCardPrinter();
reader = new SCMSmartCardReader();
di = DataCardPrinter.InitializeDI();
printer.CreateHDC();
Assert.AreNotEqual(printer.Hdc, 0, "Creating HDC Failed");
Assert.Greater(di.cbSize, 0);
int res = ICE_API.SetInteractiveMode(printer.Hdc, true);
Assert.Greater(res, 0, "Interactive Mode Failed");
res = ICE_API.StartDoc(printer.Hdc, ref di);
Assert.Greater(res, 0, "Start Document Failed");
res = ICE_API.StartPage(printer.Hdc);
Assert.Greater(res, 0, "Start Page Failed");
res = ICE_API.RotateCardSide(printer.Hdc, 1);
Assert.Greater(res, 0, "RotateCardSide Failed");
res = ICE_API.FeedCard(printer.Hdc, ICE_API.ICE_SMARTCARD_FRONT + ICE_API.ICE_GRAPHICS_FRONT);
Assert.Greater(res, 0, "FeedCard Failed");
bool bRes = reader.EstablishContext();
Assert.True(bRes, "EstablishContext Failed");
bRes = reader.ConnectToCard();
Assert.True(bRes, "Connect Failed");
bRes = reader.WriteToCard("123456");
Assert.True(bRes, "Write To Card Failed");
string read = reader.ReadFromCard();
Assert.AreEqual("123456", read, "Read From Card Failed");
bRes = reader.DisconnectFromCard();
Assert.True(bRes, "Disconnect Failde");
res = ICE_API.SmartCardContinue(printer.Hdc, ICE_API.ICE_SMART_CARD_GOOD);
Assert.Greater(res, 0, "SmartCardContinue Failed");
res = ICE_API.EndPage(printer.Hdc);
Assert.Greater(res, 0, "End Page Failed");
res = ICE_API.EndDoc(printer.Hdc);
Assert.Greater(res, 0, "End Document Failed");
}
Тест работает, но принципы нарушены — он проверяет несколько функций, и очень много. И каждая следующая функция зависит от результата предыдущей. Теперь мы подошли к вопросу: как мне следует подходить к модульному тестированию в этих обстоятельствах?