Testing... So lets say you're writing some wrapper library, for example around the named pipe API* in Windows. So you're wrapping CreateNamedPipe, CreateFile, ReadFile, WriteFile etc.

Testing... So lets say you're writing some wrapper library, for example around the named pipe API* in Windows. So you're wrapping CreateNamedPipe, CreateFile, ReadFile, WriteFile etc.

So what's the best way of writing tests for something like this? Drop testing of the lower-levels and only test that the higher-level stuff works? Ie that you can create a pipe, connect to it and the data sent is received ok?

It seems unit testing is of limited value, as each call in isolation is not very useful. Maybe I'm missing something? I'll admit I'm rather inexperienced when it comes to unit testing.

Input very much appreciated.

*No, I'm not writing a named pipe library.

Comments

  1. You can only do unit testing if you create an interface for the API, and implement both a real and a test double for that interface. I probably call it integration testing instead of unit testing, but you can use the standard unit testing libraries to get such a thing going.

    ReplyDelete
  2. If anyone writes a library like this, please make the API platform agnostic.

    ReplyDelete
  3. Jeroen Wiert Pluimers Just so I understand correctly, abstract away CreateFile/ReadFile etc behind some interface,  and then have some test implementations and one forwarding to the WinAPI?

    ReplyDelete
  4. Jeroen Wiert Pluimers I am working on an actual library though, and while I'd like to make it platform agnostic, the problem is simply that I'm almost entirely unfamiliar with the relevant API's on the other platforms.

    My library will wrap all OS calls, so no "bare handles" are seen by the users or similar, but it's still easy to make it impossible to port simply because the concepts don't map.

    ReplyDelete
  5. Asbjørn Heid that's the level of abstraction you're after.

    ReplyDelete
  6. Jeroen Wiert Pluimers Yeah, like I said though, I'm not writing a named pipe library but something else. I picked named pipes because it illustrates the issue while being fairly well known (or so I imagined).

    That said, I certainly agree that a named pipe library should be multiplatform, or at least be possible to port without jumping through hoops.

    ReplyDelete
  7. Unit tests are only for software parts in isolation. As a named pipe by its definition is some external dependency you cannot write a unit test for these parts. But unit tests are only one of many different kinds of software tests. And when talking about the well known frameworks, they work the same for unit tests and integration tests (we are doing them both with DUnit at work).
    Unit tests would come into play when you create some component/class that consumes the NamedPipe (or other protocols). In such case you might want to abstract the protocol behind an interface and then you can mock that interface and test the component in isolation by controlling the behavior of the protocol through the mock.

    ReplyDelete
  8. Stefan Glienke Even in "The Art Of Unit Testing" book, there are several levels of isolation. You can test the communication layer in isolation from the DB, for instance.
    So there are several levels, not just "unit test", then "integration tests". The more levels you could tests, the better.
    It is IMHO perfectly valid to consider named pipe testing as some kind of "unit testing". It is no problem to create a local named pipe server, then use it to validate communication with a named pipe client during the whole regression tests.
    Mocking could be done at other levels, e.g. for database.

    ReplyDelete
  9. A. Bouchez At the end of the day it doesn't matter how we call it - important is that you properly test your code.

    ReplyDelete
  10. Thanks for the input guys, really appreciated.


    Multithreaded testing would indeed be required for this project down the line. I see Synopse uses their own testing framework for this. As far as I can see the current "standard" tools, DUnit and DUnitX does not offer anything help here.

    ReplyDelete
  11. My user-facing API is all interfaces and records, no classes. Records due to operator overloading.

    Struggling to see when mocks are worth it. I'll keep them in mind as I continue increasing test coverage.

    ReplyDelete
  12. You should also have interfaces at the other end, e.g. for data access or cross-cutting features (like reporting or email sending).
    You would then be able to test your user-facing API (i.e. the application layer) via its interface, without any UI, then use the other end interfaces to stub or mock a database.

    ReplyDelete

Post a Comment