I'm trying to apply the TDD approach to an I/O library that I'm writing to manage custom archive files that contain my game's resources and assets. This is a learning process so I'm trying to follow the rules of TDD rigorously, but I'm falling on a few issues for which I don't see an easy way out without breaking TDD. I'd like to have some advice on this.
TDD says "test behavior, not implementation", but when the whole point of a class is its implementation, how does TDD go about it? I'm asking this because in my game's I/O library, I have the OutputStream class which is the base class for all stream objects that write output somewhere, and then I have the BufferedOutputStream that implements buffering and flushes the buffer when it's full. (Into another OutputStream that may be a FileOutputStream, a MemoryOutputStream, a mock object for unit tests, etc.)
Basically, I'd like to test that the buffering works, but this is about implementation, not about behavior. It's easy to test that the Flush method works by using a mock object for the buffered stream's output and checking that its Write method is called, but how do I test that the actual buffering works correctly? The simplest method to make every tests pass is to just not bother with buffering and write the input directly in the output stream. Or more realistically, I could have a bugged buffering algorithm that flushes the buffer when it is not full, and I don't know how I could write a unit test that fails without breaking encapsulation and knowing volatile and private implementation details such as the size of the buffer. This is obviously private stuff, and if I add public method to change and access the buffer, I'm breaking encapsulation, bloating the API and potentially adding more ways to break the object's internal state.
Also, I'd like to know if I'm right to assume that classes and methods that interface directly with the operating system cannot be tested until integration tests, and thus should not be written until then? Again, in my I/O library, I have the FileOutputStream which is a specializtion of the OutputStream that writes to files. Sounds like I have to break TDD principles, otherwise I'll never write that class without unit tests.