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.
3.148.144.228