Switch to run() over setUp() and tearDown()

Changes the `Exam` case to use `run()` with custom setup and teardown functionality, as opposed to piggy backing on testunit's default `setUp` and `tearDown` hooks being called.  

This has a few advantages:

1. It simplifies the code
2. It allows users of Exam to define their own `setUp` or `tearDown` methods in their test cases without needing to call `super` to ensure the exam versions ran.
3. Simplifies the API a test runner must implement to be compatible with Exam to just `run()`.

This PR also has some further code cleanup and readability improvements.