Unit test method with NSData dataWithContentsOfURL
Asked Answered
K

1

1

I am developing an iOS app and I am trying to do it with test-driven development. I've been reading a lot on the subject and one of the things I came across in a book is that tests are supposed to be fast, repeatable and reliable. As a consequence, when writing a test for networking code, the test should "simulate" the network, so that it can be executed regardless of network availability.

In my code I have a method that retrieves an image from the internet with a URL, scales it and stores it in the file system using dataWithContentsOfURL from NSData:

+ (void) getImage:(NSString *)imageUrl {

    UIImage *image = [UIImage imageWithData:
        [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]]];

    // Scale image
    // Save image in storage 
}

My question is: what would be a good approach to test this method, so that the test passes when the code is correct and fails when it isn't, without taking into account possible network failures?

Currently in my tests I am ignoring the fact that the method needs a connection, and just expect the outcome to be correct. However, I already see how this can become a problem when my test suit grows, since they already take a considerable amount of time to run. More importantly, I don't want my tests to fail just because there isn't a good network connection, as I believe that is not their purpose. I appreciate any suggestions.

Kingdom answered 9/10, 2013 at 1:23 Comment(0)
C
1

Your intention to keep your tests fast, reliable and repeatable are good ones. Removing the dependency on the network is a great way to help achieve those goals.

Instead of being locked into the method as it is now, remember that the tool you are trying to use is called test-DRIVEN development. Tests aren't just a wrapper to make sure your code works as written. Its a way to discover ways that your code can be improved to make it more testable, reliable, reusable, etc.

To eliminate the network dependency, you could consider passing a URL (your parameter's name is already imageURL) instead of a string. This way you can create URL to the local file system instead of to a location on the network.

I also notice that your method is really doing a lot of work. A name that describes what its really doing might be loadImageFromURLAndScaleItAndSaveItToDisk:. Why not break it up into several smaller, more testable methods? Maybe one that loads an image from a URL, one that scales an image and one that saves an image to the local file system. You could test each individual portion and then make another unit test that tests your original method by comparing its results against the results of calling the smaller methods in order.

I guess I would also say that keeping tests fast, reliable and repeatable is a good goal, but if you want make a test that is 'slower' or 'not 1000% reliable' that OK. A test that provides value to you is better than not writing a test because you don't think its a good enough test.

I know most of that is general, but I hope it helps.

Chavis answered 9/10, 2013 at 1:54 Comment(1)
Passing a URL to a image that is in the local file system is a great way to solve my problem, thanks. My real method works very similar to your suggestion, using two smaller methods for scaling and storing the image, I just omitted that code because I thought it wasn't relevant (maybe it was). I will change the name of the method to one that is more descriptive in the context of my application.Kingdom

© 2022 - 2024 — McMap. All rights reserved.