I'm the creator of TestNG and author of the "Next Generation Testing" book, so here are a few (obviously biased) thoughts.
For functional (or end to end / integration / system, whatever term you prefer) testing, TestNG offers a few features that JUnit doesn't have and that users have found very useful:
Groups. Once you have compiled your tests, you can just ask TestNG to run all the "front-end" tests, or "fast", "slow", "database", etc...
Support for multithreaded testing. This has two different meanings:
1) You can tell TestNG to run all your tests concurrently in thread pools that you define (one line change in an XML file). This is very configurable so that tests that are not multithreaded can still be run in single threads.
2) You can tell TestNG to invoke your test methods n times from p threads. This gives you a good idea of how thread safe the code you are testing is.
- Test dependencies and deterministic ordering. This is very useful for integration testing where it's very common to see test methods that need prior test methods to succeed before they can even run. TestNG is very popular in the Selenium community for this specific reason ("don't bother testing this page of my web site if the login test failed").
Another immediate advantage of test dependencies is that TestNG can tell you "1 method failed, 99 methods skipped", which is a much more accurate result than "100 methods failed".
TestNG has many, many more features and I'm happy to answer questions here or on our mailing-list (http://groups.google.com/group/testng-users ).