Why can classes being unit tested with JUnit not have a main? - java

My lecturer mentioned this before, but I don't really understand why this is the case. Would anyone be able to explain ?
We are writing a program to compute an array list of prime numbers, and we have to use JUnit to ensure all members of this arraylist are prime. Why can I not use a main in testing this class ?
Thank you very much :)

Ok these answers are for the most part too complex. I think your question is more fundamental. ANd its a very good one
The answer is when you become a java developer and start writing large amount of code that get updated/fixed over time then it helps to have a separate test plug-in that will automatically run tests on your code from outside the code to check if it’s still working in the way you would expect. This means you can fix/debug different aspect of the code for whatever reason and afterwards your boss walks over and asks does the code still do what the client wanted it to do since your fix? Without complication You can answer him without complex in-main error statements, which are mixed up with the normal program output (and slow down the code in non test conditions), but with a pretty green junit bar that says it all still works. You won’t see the value of this until you develop large projects and you have hundreds of tests to do. In addition junit has a number of other tricks up its sleeves...

Because JUnit is providing a main that calls the functions that you provide in your classes. You can still have your own main functions; they just won't get used when you run JUnit. You can use main functions to test your own classes individually, but using JUnit has some advantages as described in org.life.java's answer.

You can, it just wouldn't be recommended. If you write a unit test for testing it, then you can use the junit test runner to run the test and to produce a report indicating whether it passed or failed. If you don't do this then you'll need to code your own report mechanism.
Unit tests have the following structure normally:
Create test infrastructure
Execute test
Validate passed
Your situation has something similar and is thus a good candidate for using junit.
The unit testing API's available provide you with useful utilities that you would ordinarily have to code yourself.
Why don't you try both approaches and see for yourself.

In unit testing you are not testing anything as a whole. A unit test must test a UNIT normally a method. So you should write the method that computes your array, and use Junit to just test the method.
The main method is just an entrypoint and it "defines" the flow of the procedure. In unit testing we don't worry on flow. We just forcus on the unit. The program flow is verified using the System/Component test, not by the unit tests.

Because JUnit tests are run by a framework not as a standard console application.
The JUnit test runner finds the tests by reflection.
See the documentation here.

See: org.junit.runner.JUnitCore.main(String...), something like that is underlying.

Related

How to start writing Unit Tests for SpringBoot(The proper way)?

I'm new to the world of unit testing in Spring and with some research I think I'll be using Junit5 with mockito and AssertJ library for the same. I am just starting out and it does look really confusing.
1st Question: Do we write our units first?? meaning our controller methods or service methods or any unit.. Do we write those firsts and then write tests for them or Do we first design our tests thinking ok, this methods needs to do this so I'll be writing my tests and then actually implement what I have to implement? I know this a bit silly of a question but I want to know how people go about it this in their work.
2nd Question: Suppose we write our tests, it fails for a certain unit. After it fails, what should be my first approach i.e. should I be thinking that the way I wrote the test was bad, so I need to properly write the test in order for the test to pass, or should I be like, ok my unit must have been bad, I'll change or refactor my code right away and then again test it after the refactoring? What is the 'thing' to do just after your test fails for some unit?
3rd Question/Help: Testing simple CRUD methods seems okayish and there are a lot of resources for it although it's still confusing.. Could someone recommend me a github repo or a link or any source where unit tests have been written for some complex functions with some actual logic inside it and not only CRUD operations? I want to see how tests are written for the logic inside the code and how things are actually tested.
Any help would be highly valued. Thank-you, Have a good day.
You are asking if you should to "Test Driven Development" (TDD for short) , where writing test first is the basic idea. But since you did not write any tests yet, start small, write the test afterwards, and as soon you feel comfortable writing tests, write all test before implementing. And read more about "TDD", google is you friend.
this depends if you trust the test code more than the production code or vice versa. Of cause, test code can also be buggy. But test code should actually be easier to understand, so it should be easier to decide who much you can trust it.
See https://medium.com/#sheikarbaz5/spring-boot-with-tdd-test-driven-development-part-i-be1b90da51e or https://livebook.manning.com/book/spring-boot-in-action/chapter-4/

How can I run a test class only if another test was passed?

I am doing some Junit testing and I need to know how to run a Test class only if a specific test from another class was passed.
There is 'Categories' feature in JUnit. (See: https://github.com/junit-team/junit/wiki/Categories)
This question has already been replied in this post
In the #Before function you need to retreive a runtime value from your system and check that it matches your requirement. Everything will stop if it doesn't
IMHO, This is bad practice, even in a well-designed Integration test-suite. I would encourage you to rethink your overall test class design.
If these tests are truly meant to be unit tests, they should be atomic and independent of each other. See this post for a good read.
Having said that, I have often used JUnit 4.x to build & run rather large suites of Integration tests (backend functional tests that test a RESTful services responses). If this is your use case, I recommend restructuring your tests such that you never have one test in TestClassA depend on a test in TestClassB. That is a bad idea, as it will making your tests more fragile. And difficult for other devs to understand the intention of your tests, taken together as a whole.
When I have found that I have dependencies across multiple test classes, I have factored out a "test-superclass" to both test classes and do my "setup work" in that superclass. Or you can factor out a utility class that contains static methods for creating somewhat complex test conditions to start with.
But, even using JUnit as a vehicle to run these kind of "integration" tests should be done with caution and careful intent.

List all the Junit Test Cases in Eclipse

I'm using Junit with Eclipse. I have created test cases for few of the methods in my project. Is there any way/plugin to find the list of classes for which the test cases have been created(so that I need not manually check whether test cases created for all methods)?
You should look into using Code coverage tools, that are designed to do exactly this by telling you for instance:
which lines are covered by your tests
which branches of loops, ifs, switches, etc. are covered by your tests
More unit plug-in decorates all classes for which test classes are written.
Check here.
Using code coverage tools:
If used code coverage tools, then user has to run this(Ex:Eclemma) tool again and again to cover all use cases and merge the results of each run to check the method coverage.This takes more time.
Even this procedure is automated then also user has to open all source files to check whether the method is covered or not. See coverage view.
If the method is marked as 100% coverage that doesn’t mean that test case was written for that method separately. Because other method may called this method internally.
So using code coverage tool it is not possible to decide whether test cases were written for all the methods of all the classes.

How can I improve my junit tests

Right my junit tests look like a long story:
I create 4 users
I delete 1 user
I try to login with the deleted user and make sure it fails
I login with one of the 3 remaining user and verify I can login
I send a message from one user to the other and verify that it appears in the outbox of the sender and in the inbox of the receiver.
I delete the message
...
...
Advantages:
The tests are quite effective (are very good at detecting bugs) and are very stable, becuase they only use the API, if I refactor the code then the tests are refactored too. As I don't use "dirty tricks" such as saving and reloading the db in a given state, my tests are oblivious to schema changes and implementation changes.
Disadvantages:
The tests are getting difficult to maintain, any change in a test affects other tests. The tests run 8-9 min which is great for continuous integration but is a bit frustrating for developers. Tests cannot be run isolated, the best you can do is to stop after the test you are interested in has run - but you absolutely must run all the tests that come before.
How would you go about improving my tests?
First, understand the tests you have are integration tests (probably access external systems and hit a wide range of classes). Unit tests should be a lot more specific, which is a challenge on an already built system. The main issue achieving that is usually the way the code is structured:
i.e. class tightly coupled to external systems (or to other classes that are). To be able to do so you need to build the classes in such a way that you can actually avoid hitting external systems during the unit tests.
Update 1: Read the following, and consider that the resulting design will allow you to actually test the encryption logic without hitting files/databases - http://www.lostechies.com/blogs/gabrielschenker/archive/2009/01/30/the-dependency-inversion-principle.aspx (not in java, but ilustrates the issue very well) ... also note that you can do a really focused integration tests for the readers/writers, instead of having to test it all together.
I suggest:
Gradually include real unit tests on your system. You can do this when doing changes and developing new features, refactoring appropriately.
When doing the previous, include focused integration tests where appropriate. Make sure you are able to run the unit tests separated from the integration tests.
Consider your tests are close to testing the system as a whole, thus are different from automated acceptance tests only in that they operate on the border of the API. Given this think about factors related to the importance of the API for the product (like if it will be used externally), and whether you have good coverage with automated acceptance tests. This can help you understand what is the value of having these on your system, and also why they naturally take so long. Take a decision on whether you will be testing the system as a whole on the interface level, or both the interface+api level.
Update 2: Based on other answers, I want to clear something regarding doing TDD. Lets say you have to check whether some given logic sends an email, logs the info on a file, saves data on the database, and calls a web service (not all at once I know, but you start adding tests for each of those). On each test you don't want to hit the external systems, what you really want to test is if the logic will make the calls to those systems that you are expecting it to do. So when you write a test that checks that an email is sent when you create an user, what you test is if the logic calls the dependency that does that. Notice that you can write these tests and the related logic, without actually having to implement the code that sends the email (and then having to access the external system to know what was sent ...). This will help you focus on the task at hand and help you get a decoupled system. It will also make it simple to test what is being sent to those systems.
unit tests should - ideally - be independent, and able to run in any order. So, I would suggest that you:
break up your tests to be independent
consider using an in-memory database as the backend for your tests
consider wrapping each test or suite in a transaction that is rolled back at the end
profile the unit tests to see where the time is going, and concentrate on that
if it takes 8 minutes to create a few users and send a few messages, the performance problem may not be in the tests, rather this may be a symptom of performance problems with the system itself - only your profiler knows for sure!
[caveat: i do NOT consider these kinds of tests to be 'integration tests', though i may be in the minority; i consider these kinds of tests to be unit tests of features, a la TDD]
Now you are testing many things in one method (a violation of One Assertion Per Test). This is a bad thing, because when any of those things changes, the whole test fails. This leads it to not being immediately obvious why a test failed and what needs to be fixed. Also when you intentionally change the behaviour of the system, you need to change more tests to correspond the changed behaviour (i.e. the tests are fragile).
To know what kind of tests are good, it helps to read more on BDD: http://dannorth.net/introducing-bdd http://techblog.daveastels.com/2005/07/05/a-new-look-at-test-driven-development/ http://jonkruger.com/blog/2008/07/25/why-behavior-driven-development-is-good/
To improve the test that you mentioned, I would split it into the following three test classes with these context and test method names:
Creating user accounts
Before a user is created
the user does not exist
When a user is created
the user exists
When a user is deleted
the user does not exist anymore
Logging in
When a user exists
the user can login with the right password
the user can not login with a wrong password
When a user does not exist
the user can not login
Sending messages
When a user sends a message
the message appears in the sender's outbox
the message appears in the reciever's inbox
the message does not appear in any other message boxes
When a message is deleted
the message does not anymore exist
You also need to improve the speed of the tests. You should have a unit test suite with good coverage, which can run in a couple of seconds. If it takes longer than 10-20 seconds to run the tests, then you will hesitate to run them after every change, and you lose some of quick feedback that running the tests gives you. (If it talks to the database, it's not a unit test, but a system or integration test, which have their uses, but are not fast enough to be executed continually.) You need to break the dependencies of the classes under test by mocking or stubbing them. Also from your description it appears that your tests are not isolated, but instead the tests depend on the side-effects caused by previous tests - this is a no-no. Good tests are FIRST.
Reduce dependencies between tests. This can be done by using Mocks. Martin Fowler speaks about it in Mocks aren't stubs, especially why mocking reduces dependencies between tests.
You can use JExample, an extension of JUnit that allows test methods to have return values that are reused by other tests. JExample tests run with the normal JUnit plugin in Eclipse, and also work side by side with normal JUnit tests. Thus migration should be no problem. JExample is used as follows
#RunWith(JExample.class)
public class MyTest {
#Test
public Object a() {
return new Object();
}
#Test
#Given("#a")
public Object b(Object object) {
// do something with object
return object;
}
#Test
#Given("#b")
public void c(Object object) {
// do some more things with object
}
}
Disclaimer, I am among the JExample developers.
If you use TestNG you can annotate tests in a variety of ways. For example, you can annotate your tests above as long-running. Then you can configure your automated-build/continuous integration server to run these, but the standard "interactive" developer build would not (unless they explicitly choose to).
This approach depends on developers checking into your continuous build on a regular basis, so that the tests do get run!
Some tests will inevitably take a long time to run. The comments in this thread re. performance are all valid. However if your tests do take a long time, the pragmatic solution is to run them but not let their time-consuming nature impact the developers to the point that they avoid running them.
Note: you can do something similar with JUnit by (say) naming tests in different fashions and getting your continuous build to run a particular subset of test classes.
By testing stories like you describe, you have very brittle tests. If only one tiny bit of functionality is changing, your whole test might be messed up. Then you will likely to change all tests, which are affected by that change.
In fact the tests you are describing are more like functional tests or component tests than unit tests. So you are using a unit testing framework (junit) for non-unit tests. In my point of view there is nothing wrong to use a unit testing framework to do non-unit tests, if (and only if) you are aware of it.
So there are following options:
Choose another testing framework which supports a "story telling"-style of testing much better, like other user already have suggested. You have to evaluate and find a suitable testing framework.
Make your tests more “unit test”-like. Therefore you will need to break up your tests and maybe change your current production code. Why? Because unit testing aims on testing small units of code (unit testing purists suggest only one class at once). By doing this your unit tests become more independent. If you change the behavior of one class, you just need to change a relatively small amount of unit test code. This makes your unit test more robust. During that process you might see that your current code does not support unit testing very well -- mostly because of dependencies between classes. This is the reason that you will also need to modify your production code.
If you are in a project and running out of time, both options might not help you any further. Then you will have to live with those tests, but you can try to ease your pain:
Remove code duplication in your tests: Like in production code eliminate code duplication and put the code into helper methods or helper classes. If something changes, you might only need to change the helper method or class. This way you will converge to the next suggestion.
Add another layer of indirection to your tests: Produce helper methods and helper classes which operate on a higher level of abstraction. They should act as API for your tests. These helpers are calling you production code. Your story tests should only call those helpers. If something changes, you need to change only one place in your API and don't need to touch all your tests.
Example signatures for your API:
createUserAndDelete(string[] usersForCreation, string[] userForDeletion);
logonWithUser(string user);
sendAndCheckMessageBoxes(string fromUser, string toUser);
For general unit testing I suggest to have a look into XUnit Test Patterns from Gerard Meszaros.
For breaking dependencies in your production tests have a look into Working Effectively with Legacy Code from Michael Feathers
In addition to the above, pick up a good book on TDD (I can recommend "TDD and Acceptance TDD for Java Developers"). Even though it will approach from a TDD point of view there is alot of helpful information about writing the right kind of unit tests.
Find someone who has alot of knowledge in the area and use them to figure out how you can improve your tests.
Join a mailing list to ask questions and just read the traffic coming through. The JUnit list at yahoo (something like groups.yahoo.com/junit). Some of the movers and shakers in the JUnit world are on that list and actively participate.
Get a list of the golden rules of unit tests and stick them on your (and others) cubicle wall, something like:
Thou shalt never access an external system
Thou shalt only test the code under test
Thou shalt only test one thing at once
etc.
Since everyone else is talking about structure I'll pick different points. This sounds like a good opportunity to profile the code to find bottleknecks and to run it through code coverage to see if you are missing anything (given the time it takes to run it the results could be interesting).
I personally use the Netbeans profiler, but there are ones in other IDEs and stand alone ones as well.
For code coverage I use Cobertura, but EMMA works too (EMMA had an annoyance that Cobertura didn't have... I forget what it was and it may not be an issue anymore). Those two are free, there are paid ones as well that are nice.

JUnit vs TestNG [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 3 years ago.
Improve this question
At work we are currently still using JUnit 3 to run our tests. We have been considering switching over to JUnit 4 for new tests being written but I have been keeping an eye on TestNG for a while now. What experiences have you all had with either JUnit 4 or TestNG, and which seems to work better for very large numbers of tests? Having flexibility in writing tests is also important to us since our functional tests cover a wide aspect and need to be written in a variety of ways to get results.
Old tests will not be re-written as they do their job just fine. What I would like to see in new tests though is flexibility in the way the test can be written, natural assertions, grouping, and easily distributed test executions.
I've used both, but I have to agree with Justin Standard that you shouldn't really consider rewriting your existing tests to any new format. Regardless of the decision, it is pretty trivial to run both. TestNG strives to be much more configurable than JUnit, but in the end they both work equally well.
TestNG has a neat feature where you can mark tests as a particular group, and then easily run all tests of a specific group, or exclude tests of a particular group. Thus you can mark tests that run slowly as in the "slow" group and then ignore them when you want quick results. A suggestion from their documentation is to mark some subset as "checkin" tests which should be run whenever you check new files in. I never saw such a feature in JUnit, but then again, if you don't have it, you don't REALLY miss it.
For all its claims of high configuration, I did run into a corner case the a couple weeks ago where I couldn't do what I wanted to do... I wish I could remember what it is, but I wanted to bring it up so you know that it's not perfect.
The biggest advantage TestNG has is annotations... which JUnit added in version 4 anyways.
First I would say, don't rewrite all your tests just to suit the latest fad. Junit3 works perfectly well, and the introduction of annotations in 4 doesn't buy you very much (in my opinion). It is much more important that you guys write tests, and it sounds like you do.
Use whatever seems most natural and helps you get your work done.
I can't comment on TestNG b/c I haven't used it. But I would recommend unitils, a great wrapper for JUnit/TestNG/DBUnit/EasyMock, regardless of which route you take. (It supports all the flavors mentioned above)
TestNG's biggest draw cards for me include its support test groups, and more importantly - test group dependencies (marking a test as being dependent of a group causes the tests to simply skip running when the dependent group fails).
TestNG's other big draw cards for me include test parameters, data providers, annotation transformers, and more than anything - the vibrant and responsive user community.
Whilst on the surface one might not think all of TestNGs features above might not be needed, once you start to understand the flexibility bring to your tests, you'll wonder how you coped with JUnit.
(disclaimer - I've not used JUnit 4.x at all, so am unable to really comment on advances or new features there).
About a year ago, we had the same problem. I spent sometime considering which move was better, and eventually we realized that TestNG has no 'killer features'. It's nice, and has some features JUnit 4 doesn't have, but we don't need them.
We didn't want people to feel uncomfortable writing tests while getting to know TestNG because we wanted them to keep writing a lot of tests.
Also, JUnit is pretty much the de-facto standard in the Java world. There's no decent tool that doesn't support it from the box, you can find a lot of help on the web and they added a lot of new features in the past year which shows it's alive.
We decided to stick with JUnit and never looked back.
Cheers to all the above. Some other things I've personally found I like more in TestNG are:
The #BeforeClass for TestNG takes place after class creation, so you aren't constrained by only being able to call static methods of your class in it.
Parallel and parameterized tests, maybe I just don't have enough of a life... but I just get a kick writing one set of Selenium tests, accepting a driver name as a parameter. Then defining 3 parallel test groups, 1 each for the IE, FF and Chrome drivers, and watching the race! I originally did 4, but way too many of the pages I've worked on break the HtmlUnit driver for one reason or another.
Yeah, probably need to find that life. ;)
I wanted to share the one I encountered today. I found built-in Parameterized runner is quite crude in Junit4 as compare to TestNG (I know each framework has its strengths but still). The Junit4 annotation #parameters is restricted to one set of parameters. I encountered this problem while testing the valid and invalid behavior for functionality in same test class. So the first public, static annotated method that it finds will be used, but it may find them in any order. This causes us to write different classes unnecessarily. However TestNG provides clean way to provide different kind of data providers for each and every method. So we can test the same unit of code with valid and invalid way in same test class putting the valid/invalid data separately. I will go with TestNG.
Also one more advantage of TestNG is supporting of parallel testing. In our era of multicores it's important, i think.
I also used both frameworks. But i using hamcrest for assertations. Hamcrest allows you easily write your own assert method. So instead of
assertEquals(operation.getStatus(), Operation.Status.Active);
You can write
assertThat(operation, isActive());
That gives you opportunity to use higher level of abstraction in your tests. And this makes your tests more robust.
JUnit 4 Vs TestNG – Comparison by mkyong.com ( updated on 2013).
Conclusion: I suggest to use TestNG as core unit test framework for Java project, because TestNG is more advance in parameterize testing, dependency testing and suite testing (Grouping concept).
TestNG is meant for functional, high-level testing and complex integration test. Its flexibility is especially useful with large test suites.
In addition, TestNG also cover the entire core JUnit4 functionality. It’s just no reason for me to use JUnit anymore.
In simple terms, TestNG = JUnit + lot more. So, Why debate ? go and
grab TestNG :-)
You can find more detailed comparison here.
Why we use TestNG instead of JUnit?
The declaration of #BeforeClass and #AfterClass method has to be static in JUnit whereas, there is more flexibility in TestNG in the method declaration, it does not have these constraints.
In TestNG, we can parametrize tests using 2 ways. #Parameter or #DataProvider annotation.
i) #Parameter for simple cases, where key value mapping is required.(data is provided through xml file)
ii) #DataProvider for complex cases. Using 2 dimensional array, It can provide data.
In TestNG, since #DataProvider method need not be static, we can use multiple data provider methods in the same test class.
Dependency Testing: In TestNG, if the initial test fails, then all subsequent dependent tests will be skipped, not marked as failed. But JUnit marked it failed.
Grouping: Single tests can belong to multiple groups and then run in different contexts (like slow or fast tests). A similar feature exists in JUnit Categories but lacks the #BeforeGroups / #AfterGroups TestNG annotations that allow initializing the test / tearing it down.
Parallelism: If you’d like to run the same test in parallel on multiple threads, TestNG has you covered with a simple to use annotation while JUnit doesn’t offer a simple way to do so out of the box.
TestNG #DataProvider can also support XML for feeding in data, CSVs, or even plain text files.
TestNG allows you to declare dependencies between tests, and skip them if the dependency test didn’t pass.
#Test(dependsOnMethods = { "dependOnSomething" })
This functionality doesn’t exist in JUnit
Reporting:
TestNG reports are generated by default to a test-output folder that includes HTML reports with all of the test data, passed/failed/skipped, how long did they run, which input was used and the complete test logs. In addition, it also exports everything to an XML file which can be used to construct your own report template.
On the JUnit front, all of this data is also available via XML, but there’s no out of the box report and you need to rely on plugins.
Resource Link:
A Quick JUnit vs TestNG Comparison
JUnit vs. TestNG: Which Testing Framework Should You Choose?
A good difference is given in this tutorial side by side: TestNG Vs JUnit: What's the Difference?
A couple of additions to Mike Stone's reply:
1) The most frequent thing I use TestNG's groups for is when I want to run a single test method in a test suite. I simply add this test to the group "phil" and then run this group. When I was using JUnit 3, I would comment out the entries for all methods but the one I wanted to run in the "suite" method, but then would commonly forget to uncomment them before checkin. With the groups, I no longer have this problem.
2) Depending on the complexity of the tests, migrating tests from JUnit3 to TestNG can be done somewhat automatically with sed and creating a base class to replace TestCase that static imports all of the TestNG assert methods.
I have info on my migration from JUnit to TestNG here and here.
My opinion about what makes TestNG truly far more powerful:
1. JUnit still requires the before/after class methods to be static, which limits
what you can do prior to the running of tests, TestNG never has this issue.
2. TestNG #Configuration methods can all take an optional argument to their
annotated methods in the form of a ITestResult, XmlTest, Method, or
ITestContext. This allows you to pass things around that JUnit wouldn't
provide you. JUnit only does this in listeners and it is limited in use.
3. TestNG comes with some pre-made report generation classes that you can copy
and edit and make into your own beautiful test output with very little
effort. Just copy the report class into your project and add a listener
to run it. Also, ReportNG is available.
4. TestNG has a handful of nice listeners that you can hook onto so you can do
additional AOP style magic at certain phases during testing.
Your question seems two folded to me. On one had you would like to compare two test frameworks, on the other hand you would like to implement tests easily, have natural assertions, etc...
Ok, firstly JUnit has been playing catchup with TestNG in terms of functionality, they have bridged the gap some what with v4, but not well enough in my opinion. Things like annotations and dataproviders are still much better in TestNG. Also they are more flexible in terms of test execution, since TestNG has test dependency, grouping and ordering.
JUnit still requires certain before/after methods to be static, which limits what you can do prior to the running of tests, TestNG never has this issue.
TBH, mostly the differences between the two frameworks don't mean much, unless your focusing on integration/automation testing. JUnit from my experience is built from the ground up for unit testing and is now being pushed towards higher levels of testing, which IMO makes it the wrong tool for the job. TestNG does well at unit testing and due to its robust dataproviding and great test execution abilities, works even better at integration/automation test level.
Now for what I believe is a separate issue, how to write well structured, readable and maintainable tests. Most of this I am sure you know, but things like Factory Pattern, Command Pattern and PageObjects (if your testing websites) are vital, it is very important to have a layer of abstraction between what your testing (SUT) and what the actual test is (assertions of business logic). In order to have much nicer assertions, you can use Hamcrest. Make use of javas inheritance/interfaces to reduce repetition and enforce commonality.
Almost forgot, also use the Test Data Builder Pattern, this coupled with TestNG's dataprovider annotation is very useful.

Categories