I have never written unit tests before, for various reasons. I have a chance to write tests now, comfortably, because I have a small app to make from scratch.
However, I'm a bit puzzled. The application is supposed to use a printer with a smart card reader to program data on a smart card. So here's the sequence of actions: Create device context, set printer mode, initialize a document, feed a card into the printer, connect to the card with a reader, write something to the card, move the card out, end document, dispose of device context.
Okay, unit tests are supposed to test one function for each test, and each test is supposed to run independently of the result of other tests. But let's see - I can not test writing to smart card if I did not position it properly in the printer and if I have not connected to it. And I can not mock this by software - I can only test if writing actually happened if the real card is positioned properly and connected to. And if connecting to card will fail, there's no way to test writing to card - so the test independence principle is broken.
So far I came up with a test like this (there are also other test which are 'proper' and test other things too)
[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");
}
The test is working, but the principles are broken - it tests multiple functions, and a lot of them. And each following function depends on the outcome of the previous one. Now, we come to the question: How should I approach unit testing in these circumstances?