Compared to JUnit, TestNG is better on integration and end-to-end tests (e.g. with Selenium).
- No need to create own Thread objects (Use annotations)
- Dependencies between tests:
- fail fast: run Selenium tests only if application was deployed properly, run full system tests only if smoke tests passed. The feedback will be much quicker in case of failed tests.
- logical dependencies between tests: execute shouldDeleteUserFromDatabase test only if shouldAddUserToDatabase worked> It gives you a much more realistic error information - 1 tests has failed and 99 has been skipped, which is much easier to fix than the information about 100 failed tests
- Listeners, Reporters. It is pretty easy to write your own listeners (which act in runtime) and reporters (which are invoked after the execution).
- Factories: Factories allow you to create tests dynamically.