Jamie's Space


UI Design, Unit Testing, and Related Pains


Currently I am working on merging two of the steps in the Workbench part of ArchAngel. The final two steps of the generation process used to be the actual generation of the files you wanted, and the analysis to see which files needed to be merged. This was two screens, one in which the user picked the groups of files to generate, and the other which showed conflict resolution. Only after all conflicts had been resolved could the newly generated and merged files be copied into the user’s project directory.

UI Changes

This wasn’t as easy as it could be. There is no reason why the user needs to go through an additional screen to choose the files - why not just put that on the screen with the analysis so they could choose which files they wanted to keep? So Gareth merged the two screens, shifting the file choosing part to the tree view with checkboxes, and showing the results of the analysis as an icon next to the file in the tree.

Process Changes

One thing Gareth wanted to do was generate the files in the background. I set up a process whereby the files would be generated on a background thread, and if the user changed any options in the project, the files would be regenerated. Hopefully most of the files would be generated by the time the user actually got to the final generate and merge screen. We also do the analysis on the same thread once the generation is done.

Unit Testing

This process is really the meat of the ArchAngel Workbench - the majority of the processing happens here. Thus I wanted to make sure that I wasn’t breaking anything by implementing this background processing, as I had to make a number of changes to make it thread-safe. So I embarked on a quest to make this part of the system as easy to unit test as possible.

I started by completely removing any trace of GUI code from the generation code. This meant removing the background worker references, and replacing all of the code dealing with threading with a helper class I created. This class encapsulated progress reporting and task cancellation, so that we can mock these aspects during testing.

Mocking is a major focus of this process - I want to be able to mock out as much of the system as possible in order to make the unit tests more focused. The thing with mocking/faking the major components in the system is that we can write these mocks/fakes once, and reuse them in all of our tests. This is better than relying on resetting the state of the major components - this is prone to failure if those components change in future. Also it is difficult to prevent behaviour that relies on the underlying environment, such as writing to files and reading from settings files.

On Monday I will start working on creating some mocks for these components, and will add another post with my experiences of this.