16

I've been asked to do a small side-project to supply a simple application to one of our customers. Normally I would be working on back-end code where I have all of my testing needs figured out, and I've not yet had the dubious pleasure of writing tests for the GUI, so it's a little unclear to me how I should set up the testing code and tools for an EXE.

My first instinct was to simply include the tests with the application code, however that would require supplying a number of test-specific dependencies, which I have been instructed to specifically not ship to the customer. I am also unable to squeeze out any cash for a purpose built test tool, so I need to use the tools I have at hand (StoryQ, RhinoMocks, and NUnit), which really should be more than enough to test the behavior of a simple GUI app. So as far as I can see, this leaves me with trying to strike a good balance between keeping the design really simple, or purposefully over-engineering for the sake of the tests. It seems I'm either building the app with the business logic in a separate library and testing against the library as I usually would, or finding some other mechanism to allow me to the executable without breaking out additional modules that the application design doesn't really need.

Edit:
Please note that this question is about how to structure the relationship between NUnit and my executable - as opposed to a DLL - and not about how to separate presentation and business logic.
/Edit

So my question is:

  1. Is there a specific/recommended method for configuring a simple GUI application with unit tests to allow me to adequately check state and behavior, using the tools I have at hand, and without resorting to over-engineering?
  2. Have I missed something fundamental about the way NUnit should be invoked/configured when testing an EXE (as opposed to a DLL)?
  3. Can you provide or point me in the direction of examples of how achieve all of this?

I realize that there may be more than one way to do this so I'm looking for specific implementation guidelines based on your experience.

3
  • NUnit isn't designed to test GUIs directly. You need to separate your presentation layer (i.e. view) from your data and business logic (i.e. model) so that you can test what goes into your view without using the view.
    – Bernard
    Commented Jan 25, 2012 at 21:24
  • 1
    @Bernard This question is not about layering a GUI for testing. I naturally layer all of my apps - even the trivial ones - so that really isn't a problem for me. I've edited the question to suit, and I hope that it clears up any misconceptions. :)
    – S.Robins
    Commented Jan 25, 2012 at 22:20
  • 1
    There's nothing terribly complicated in unit testing stuff in EXE's. Just have your testing DLL reference your EXE file, and you are good to go. Commented Jan 26, 2012 at 15:08

5 Answers 5

3

I mentioned in one of my comments to simoraman's answer that I had thought of a couple of ways to do this. One of my options was similar to the suggestion in Jalayn's answer to created a duplicate project and generate a DLL, while my other idea was to simply link to the files in the project where there was code I wanted to test. While both options could be made to work, they are less than ideal.

In the second case, I'd have a mess of unit dependencies to manage unless I could really tease apart the architecture to minimize dependencies. This is fine for smaller projects, but larger ones could easily become a real mess to manage. My biggest resistance to this option however is the sheer inelegance of it. Sure I could get it to work, but in doing so I effectively need to break encapsulation to test the internals of an assembly directly via source, rather than testing the via the public interfaces, which in my mind is a big no-no. Likewise having an additional project file would mean either duplicating efforts in two projects at a time, or finding a way to add project file settings automatically to two files at a time, or remembering to copy and rename the project field each time I build. This can be automated on the build server perhaps, but would be a pain to manage in the IDE. Again, it can work, but it's a kludge at best, and a nuisance at worse if you get it wrong.

The best way seems to be to do as whatsisname commented to my question, and to simply include the EXE as a reference in the test project. It turns out that an EXE is effectively treated the same way as a DLL in this case, and I am able to access all of my nicely layered classes to test whatever floats my boat.

2

I think that:

  • Your business test code should be in a separate project, testing your business code library.
  • Your GUI test code should be in a separate project, testing your GUI library. Now, how to build a GUI library instead of an executable, I attempt to answer that later.
  • If you have a my.namespace.biz.MyClass, your test class should be my.namespace.biz.MyClassTest (or MyClassTestCase).
  • If you want to test the code found in your executable target, then you should have a setup that builds an EXE, and another setup that builds a library (DLL) which is the one that you will launch your tests against.

These are the rules that I like to follow, whether it's Java or C# (except there is no EXE problem with Java of course :-) )

As for how to configure your test environment, it seems to me that you have at least these two choices:

Using MSBuild

Create a clone of your .proj file (say myproject-as-dll.proj). Change the OutputType in the cloned file from "EXE" to "Library". Using the MSBuild command you are now able to produce a library you can set as reference into your project containing NUnit test cases.

It seems to be possible to me, but I've never used it that much honestly, so I'm not sure. Plus, you may not have MSBuild on your integration test server, and I don't know if it can be separated from Visual Studio...

Using NAnt

If you are not familiar with NAnt, you will have to google up how to configure your project builds with it. Maybe check out this, it is a bit old but the author has commented the NAnt files and If find it self explanatory.(Edit: examining his file more in detail, I find his configuration file extremely reusable). He also does much more than just build, since he executes test cases and launches code coverage tools. Now, I admit I've never used NAnt, contrary to its Java counterpart and father "Ant" that I've used a lot but I see it's quite the same thing and I don't think it's that difficult to learn.

With that tool you can come up with a configuration that will allow you to:

  • build all your projects (business logic, GUI, etc.) into separate libraries
  • build your test projects
  • launch the tests (that specific part is done with the NUnit2 task).
  • examine your code coverage with the NCover task.

With a bit of more code, you could even:

  • perform nightly deployments in your integration server
  • if NAnt is available in your integration server, launch nightly integration tests with the help of scheduled tasks

All is done without changing anything in your Visual Studio files. And, really, it does not look like over-engineering to me, it's just one file. It might take you one, maybe two days to make it all work but you'll have in my opinion a good setup.

Lastly, I would give to the client all that is necessary to build, test and run the projects. I tend to think it shows your professionalism and the fact that you write code with quality in your mind (which it seems to me you do since you're looking for elegant solutions)

0

Just because project is small (initially) doesn't mean proper architecture is over-engineering. The fact that you want to write tests tells that your project isn't a completely trivial one-off hack.

You didn't mention which GUI-Framework you are using. WPF MVVM (Model-View-ViewModel) is good and allows you to write tests for all the logic quite easily. With WinForms I've heard good things about MVP (Model-View-Presenter)

4
  • I write tests for all of the code that I write. Even the stuff that you might find trivial. The only time I don't write a test is when I spike. In this case, I am shipping a one off utility to a customer, so testing is more than just a luxury, it's a requirement in order to satisfy our quality standards. In terms of "over engineering", this isn't a choice between good or bad architecture, but rather avoiding the need to impose additional layering that isn't required in this instance as the app is single purpose with a relatively short life cycle.
    – S.Robins
    Commented Jan 25, 2012 at 10:15
  • In so far as choice of gui-framework is concerned, I don't see how this will affect the way in which the testing environment is set up. I am looking for HOW specifically to implement unit tests for the GUI layer using the tools I have available. This particular answer doesn't really tell me anything about that.
    – S.Robins
    Commented Jan 25, 2012 at 10:20
  • Simoraman - If you took away the rather judgemental first paragraph, this would be getting towards an answer. Fix that and I'll remove my -1. @S.Robins note that the second paragraph is relevant - though not a full answer, it would help. If your GUI layer is thin, well structured & obvious, and all of the business logic is tested by unit tests at the Model level, then it may be that you don't need the go through the extra hassle of testing the UI explicitly.
    – Mark Booth
    Commented Jan 25, 2012 at 11:02
  • 1
    @MarkBooth Layering isn't really a problem. As simiraman mentions I can MVP, MVVM, or I can build something even thinner. I do however have some GUI specific elements that will require explicit testing, which is why I decided to write this up as a question. I have a couple of ideas, and if worse comes to worse I know that eventually I'll be able to solve the problem and write up an answer myself. I did however want to open this up to the community as I thought it would make a good question for ProgrammersSE. ;-)
    – S.Robins
    Commented Jan 25, 2012 at 11:16
0

Take a look at my answer on this question: How do I set up MVP for a Winforms solution?

I've actually written a sample application that shows how I layer, and how I test, my GUI.

reading your edit: use a test runner that integrates with your development environment. I use ReSharper.

2
  • Thanks for the ReSharper recommendation. This is a tool that I use when developing. Unfortunately it won't help when executing the tests on the integration build server. It also doesn't tell me how to configure Nunit tests to access code in an exe when testing.
    – S.Robins
    Commented Jan 26, 2012 at 4:24
  • 1
    Informally, it does. The exe is just the view, which loads the presenter, models, and viewmodels out of a class library as part of application startup. At least in my solution, the view is dumb enough that we don't test it with automated tests, and just do acceptance tests to make sure things are spelled right and buttons are where they should be. NUnit-testing a dll is very easy to do.
    – Bryan B
    Commented Jan 26, 2012 at 16:16
0

I had written Nunit WinForms few years back (6 yrs I guess). One thing that I remember specifically is that although its a unit test case, it also acts as end to end test case. Sometimes there isn't much to test on a front end (a simple form). So even though you are trying to test for a message box popping up on a button click, you are unintentionally testing various other methods from other layers. There are some things which you cannot automate as well. The look, feel and usability cannot be automated using automated unit testing. You will have to run some manual tests before you release.

1
  • If your customer specifies a screen should look a certain way, or should change in a certain way, then you should be able to test for these things. Capturing specifications as tests is the heart of the BDD methodology, and I've never found a situation where you couldn't - albeit creatively - find a means to automate a test. The real question is whether the testing will be of value, whether the application is factored well enough to allow you to automate all of the tests in the first place, and whether the tests will be cost effective. I agree though, that sometimes they are not.
    – S.Robins
    Commented Jan 27, 2012 at 1:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.