Exercising Options

For the next feature, I started supporting options. Perhaps the most useful option writes the retrieved content to a file, although you could always redirect the output without it. I started work on the “-O” option by updating the specification to detail curl’s behavior in [bb7347e].

The path to support this option meanders a bit. Admittedly, I did not start with a complete or clean concept of how the feature would be implemented. Rather, I started with an idea of how the arguments might be processed but only a clear understanding that the output handling might be tricky to test properly. I decided to show the messiness and the associated variations of testing rather than doing exploratory spikes and then reverting them to take a clean route. I hope the result is more informative that way.

I used the multiple URL overload of retrieve() to write the test [d451e31] as if it were designed to handle options. The initial test did not completely express the overall intent. Rather, it simply stated that given two arguments, an option and a URL, only one retrieval should occur. I accomplished this by using an anonymous inner class to create a mock, but without a mocking framework. The mock counted the calls to the single URI version of retrieve() and asserted inline that it was only called once. I missed a couple of details on the first pass and finally got the failure I expected in [4102ad1].

Commit [3422f2e] added test and logic to explicitly indicate the request for a write to a file. A little bit of back and forth—fortunately more forth than back—teased out the concept of an emit() method to handle the output [b994220], although the idea was far from fully baked.

The realization that I had scattered necessary state for output across several levels of method calls and abstractions led me to embark on a series of refactorings, starting with [87ae64d]. This included eliminating the previously created spy by testing rectifyURI() directly. Most notably, though, I created the concept of a Target, first as a nested class and eventually as a full top-level class [46978e9] with its own set of tests [dde0a09]. Target at first became the repository for the data associated with a retrieval, but it evolved to be the central entity for the functionality as well [13df657].

Some of the intermediate stages were pretty ugly, especially in the tests. Once it became clear that most of the functionality belonged in Target, I migrated the easy functionality, but other methods were trickier. The methods that had been overridden resisted movement, testimony to the dangers of coupling tests to implementation. In some cases, I had to comment out overrides before IntelliJ would allow me to move a method. Then I would uncomment them and move and adjust them to the new context. Ultimately, I achieved a cleaner set of code with which to finish the output flag feature.

After a few cleanup commits, I refactored the extractContentFromResponse() method in a way that prepared to switch entirely over to a stream-based approach for output [b00689d]. Foundation laid, commit [39461ce] removed the use of strings as an intermediate container for content. This forced several changes to existing tests, causing them to use overrides to inject a ByteArrayOutputStream to capture the output for inspection.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.148.144.228