Often times, I'll write code that is very network-centric and I'd like to write Unit Tests to be XP-compliant. However, I find that writing a test is often really difficult because there are a number of network components which need to be present which are not necessarily under control of the environment (ie the code I'm writing).
For example, I may be writing a class that forwards certain types of connections (say Java RMI connections) over pre-configured tunnels. Lets say those tunnels are created from without the JVM, so there is no practical way I can start those tunnels within my tests. How would one test this functionality in the XP way?
Can you start up an external process that sets up those tunnels with stubs at the remote end?
I have "cheated" by assuming certain external services to be available and testing interaction with them. It helps if they are standard services such as an SMTP or FTP server.
-- JayNayegandhi?
I'm not using XP as I am just starting work on a solo project for a college course, but I do want to use a test-driven approach. At the moment I am trying to get my head around a test regime for a network-centric system (my software will involve elements on at least three separate hosts). The MockObject link on this page gave some interesting ideas (along with the comments above). I'm wondering if it would be appropriate to effectively build an entire "Mock System" as part of the test harness (each major component of the final system having a corresponding mock/stub object) so each part of the system can be tested against a deterministic mockup of the rest.I am still very new to this style of work and my brain is still moving rather slower than perhaps it should. -- RobHarper
Sometimes the code I write is dependent on environmental or configuration parameters. For example, I have some code which uses SSH to relay composed faxes to a fax server. Coding UnitTests for this doesn't work, so I'll code an "environment test" - I prove that the scripts work with the proper input and output with standard UnitTests, then I write a non-destructive-type UnitTest which I run in production as part of deployment to verify that the SSH connection works. (This ensures that the SSH servers are configured for the right protocols, that DSA keys are installed, that hosts are known, that DNS resolves properly, etc., etc., etc.) -- JasonFelice
I would suggest a pragmatic combination of testing using stubs and testing using the real hardware. For problematic areas, I would create stub tunnels that exhibit the characteristics of interest and would be started by the test framework. These could be run as part of the automated test suite and would fall into the XP category of UnitTests / ProgrammerTests. For the ones that do not cause problems, I would write a test suite that is run in a test lab configuration. These would be run on a scheduled or as needed basis and would fall into the XP category of FunctionalTests / AcceptanceTests. Writing test stubs can be time consuming, so I would only create a very basic stub at first and enhance it to address failures coming out of the AcceptanceTests. -- WayneMack
In Systems Engineering (as in INCOSE) the above combination is called IntegrationTesting rather than UnitTesting, and the practice of creating software stubs and hardware rigs (such as network delay simulation hardware) is commonplace. It's not strictly unit testing as you have at least three units - transmitter, receiver and channel - and you are measuring an emergent behaviour of the combination of these. For instance, shortcomings in the transmitter or receiver may be overcome by over specifying the characteristics of the channel. The danger in relying on the use of naive stubs which don't simulate the real channel characteristics is you fall prey to the EightFallaciesOfDistributedComputing. -- PeteKirkham
If you are doing a solo project for your college I strongly suggest that you skip unit & acceptance tests. They are not worth the effort if you are not going to support this code for some time. Even more so if there will not be rigorous testing or heavy usage... -- AnonymousUser
For my OpenAX.25 project, implemented a module-level form of DependencyInjection, to provide an interface to the underlying sockets implementation. Basically, instead of calling socket(), accept(), send(), select(), etc., I make use of IPC_socket(), IPC_accept(), IPC_send(), IPC_select(), etc. These wrappers make use of function pointers which either point to the real BSD sockets implementation (during normal program startup), or to a mock interface of my choice (during unit testing). My unit tests are able to simulate normal network traffic, one or more connecting clients, rude disconnects (e.g., as if a client segfaulted), etc., as normally reported by the kernel.
It is a wonderful thing. I really encourage more module-level dependency injection for unit-testing entire libraries/modules. --SamuelFalvo?
See: MockObject