External Data File for Unit Tests

cocoa, unit-testing, xcode

Solution

In general, use a test data file only when it's necessary. There are a number of disadvantages to using a test data file:

- The code for your test is split between the test code and the test data file. This makes the test more difficult to understand and maintain.

- You want to keep your unit tests as fast as possible. Having tests that unnecessarily read data files can slow down your tests.

There are a few cases where I do use data files:

- The input is large (for example, an XML document). While you could use String concatenation to create a large input, it can make the test code hard to read.

- The test is actually testing code that reads a file. Even in this case, you might want to have the test write a sample file in a temporary directory so that all of the code for the test is in one place.

Instead of encoding the valid and invalid URLs in the file, I suggest writing the tests in code. I suggest creating a test for invalid characters, a test for invalid protocol(s), a test for invalid domain(s), and a test for a valid URL. If you don't think that has enough coverage, you can create a mini integration test to test multiple valid and invalid URLs. Here's an example in Java and JUnit:

public void testManyValidUrls() {
  UrlValidator validator = new UrlValidator();
  assertValidUrl(validator, "http://foo.com");
  assertValidUrl(validator, "http://foo.com/home");
  // more asserts here
}

private static void assertValidUrl(UrlValidator validator, String url) {
  assertTrue(url + " should be considered valid", validator.isValid(url);
}

Problem

I'm a newbie to Unit Testing and I'm after some best practice advice. I'm coding in Cocoa using Xcode. I've got a method that's validating a URL that a user enters. I want it to only accept http:// protocol and only accept URLs that have valid characters. Is it acceptable to have one test for this and use a test data file? The data file provides example valid/invalid URLs and whether or not the URL should validate. I'm also using this to check the description and domain of the error message. Why I'm doing this I've read Pragmatic Unit Testing in Java with JUnit and this gives an example with an external data file, which makes me think this is OK. Plus it means I don't need to write lots of unit tests with very similar code just to test different data. But on the other hand... If I'm testing for: - invalid characters - and an invalid protocol - and valid URLs all in the same test data file (and therefore in the same test) will this cause me problems later on? I read that one test should only fail for one reason. Is what I'm doing OK? How do other people use test data in their unit tests, if at all?

Original source