Question

this is my first step into the world on unit-testing so please be patient. I'm writing a Qt 4.8.1 C++ program and as test framework I'm using the integrated QTestLib. I should test a class that inhrerits from a base one and that loads a certain XML file to read and parse it later with a function that will return a C++ class object with the xml values that I can retrieve and set via set/get functions. The class in the constructor instantiate a QFile object and in the readXml function I use it to parse with the QXmlStreamReader the file. What's the best way to test all this class with unit-tests? I don't see how I could bypass the file-read operation to inject a own string representing the file content. Or should I use as test content a different ad-hoc XML file?

Was it helpful?

Solution

Injecting a string to represent the file contents seems like it would be the most straightforward way of testing a class such as this. However, directly instantiating a QFile instance in your class constructor makes this impossible (in other words, it's impossible to inject your dependency). Moreover, it's quite a bit of work to create a "Fake" or "Mock" version of a QFile (a.k.a. a Test Double of a QFile).

The easiest way to resolve this is to pass a QIODevice into your class constructor (QFile inherits from QIODevice). In your unit test, you can fake the contents of the file by passing in a QIODevice with the contents you wish to test. In this case, you can accomplish this with a QBuffer, which allows you to arbitrarily set its contents. As such, your class would like something like the following:

class MyXmlParser
{
   MyXmlParser(QIODevice* device);

   ...
};

Your unit test constructs the class with a QBuffer; your production code constructs it with a QFile.

Should I use a real XML file in my test?

Generally speaking, the more external dependencies your unit test has, the more costly it is to ensure that it doesn't break in the future (it potentially makes your unit test sensitive to its context). As such, it is advisable to avoid using a real XML file in order to ensure that your test is self-contained. Moreover, passing in a real XML means that you are now implicitly testing QFile as well as your XML parser (in other words, it's not longer a unit test, it's an integration test). You can generally assume that the IO device that you pass into your parser works; you only need to verify that your parser uses the IO device correctly and that it can parse the XML properly.

Consider reading through the material at xunitpatterns.com, particularly the section on Test Smells.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top