JUnit using #Before over #BeforeClass [duplicate] - java

This question already has answers here:
Difference between #Before, #BeforeClass, #BeforeEach and #BeforeAll
(7 answers)
Closed 4 years ago.
According to this answer, the #Before annotation is executed once before each test, whereas the #BeforeClass annotation is only executed once before all tests.
My intuition tells me to always use #BeforeClass, so the question is, why even use #Before? Is there a case where the #Before annotation performs better/faster than the #BeforeClass annotation?

Each test should be isolated. By using BeforeClass then the state of the previous test could be hanging about and messing up the later tests.
One generally uses BeforeClass to setup an expensive external resource and Before to reset the world (be that the external resource or local).
One final note:
performs better/faster
In this case I would say the two properties should be treated independently here (that is better!=faster). As long as the total time to run your complete tests suite is under 10 minutes then "faster" is simply not important.
Once you go above that magic ten minutes (and at this point you will definitely be talking integration tests not unit tests) then start looking for ways to make things "faster".

I'll give you an example:
Say you need to validate a form in your web application. You are going to use Selenium for that.
Your test class will have 10 tests. You don't need to open and close your webdriver browser each time you start your test suite. In such case, you iniatilize your webdrive browser on a #BeforeClass method.
However, for each validation test you need to reset your form. This action you will perform on a #Before method.
This is a very simple example, but may make things clearer.

When you use #BeforeClass it suggests that you do initialization before all the tests. So one test might depend on other one (e.g. if tests change the state of fields), so I would encourage usage of #Before, or even better to do preparations for the test method inside the method itself.
There are very rarely cases when your tests need exactly the same initial state, so why couple them together?

Related

Should I use the same variables throught entire Unit Test?

I am creating Unit Tests in Java and for each method, I create the same lists, variables, etc. On the other hand, of course I thought that I could create all of these variables as global and set their values in the setup() method (in #Before), but I am not sure if the values may be changed when running tests due to multithreading, etc. So, what is the best way for this situation?
Nothing to worry about. JUnit will create a new instance of your test class, and then run each #Before method, and only then run the #Test method, and it does that song and dance routine all over again for every #Test annotated method in that class. You're using #Before exactly as it was intended: It's for storing initialization code that is required for all the tests in that test class.
JUnit does it this way because 'test independence' is nice to have: Tests, preferably, fail or pass independent of the ordering in which you execute them.
Every so often the init process is so expensive that it's not worth it to pay the 'cost' of running it over and over again for every test. The annotation #BeforeClass exists specifically for that purpose. The javadoc of #BeforeClass even spells out that this compromises test independence and should therefore only be used if the setup work you do within such a method is sufficiently expensive (computationally or otherwise) to make that tradeoff.
In other words:
Your worries about test independence are real, but they apply to #BeforeClass. #Before doesn't suffer from this problem; that code is re-run for every test.
NB: You can toss all this out the window if you have static stuff going on. Don't have static stuff in test code unless you really know what you're doing. I assume you don't have that in which case - carry on, your tests are independent.

Adding a setUp step for multiple JUnit test classes

In a project there are multiple test classes each containing multiple test methods. Say, I want to create a database connection before running each of these test classes. The connection should be made regardless of whether I run an individual test class, multiple test classes or a test suite.
Most importantly this step should not be called over and over again in case of multiple test classes. The connection should be made only once regardless of number of test classes I'm running.
Could you suggest a design or any JUnit tips to tackle this issue ?
You could run the classes in a test suite. Refer this question and the answers provided.
Or change your design and use #BeforeClass annotation to run setup once before each test class.
Sometimes several tests need to share computationally expensive setup
(like logging into a database). While this can compromise the
independence of tests, sometimes it is a necessary optimization.
Annotating a public static void no-arg method with #BeforeClass causes
it to be run once before any of the test methods in the class. The
#BeforeClass methods of superclasses will be run before those the
current class.
Use #Before Junit annotation
When writing tests, it is common to find that several tests need
similar objects created before they can run. Annotating a public void
method with #Before causes that method to be run before the Test
method. The #Before methods of superclasses will be run before those
of the current class.
Simply introduce a superclass for all your junit classes. You can put the database connection logic in your Superclass #Before annotated method.
If you're using spring-test, then you could use the technique employed here: How to load DBUnit test data once per case with Spring Test

JUnit test failing because of the method name

Why the name of a test method may influence other tests?
I have a suite with 2 classes of tests, and when I change a method name of class1, my test in class2 is ok (green).
I noticed that both classes have a method with the same name, but the test that is failing is neither of these. However if I rename any of them, all tests are ok.
Is it okay to have 2 methods with the same name in different classes, but in the same suite? And the fact that another test fails randomly is just a coincidence?
ps: the order of tests runned is changed after I rename that method.
ps2: sorry for my bad English.
That picture can explain better my question:
There is no bug in JUnit! Our team experienced similar results, which are caused by inproper resource management. You can try to rename your failing test so they are executed first. They should turn green now, that's mostly a sign that a resource is accidently shared between tests. In that case you can try to free the resource in the tear down (#After).
Here is a little checklist to find the cause:
Are there Thread's that survive a test?
Are all Executors shutdown and terminated?
Are files or streams still open after a test?
Are all fields in the Test-class cleared/reinitialised after a test?
Avoid using static references or singletons
Don't free resource in your test method, only in the tear down method. Otherwise an exception could make this piece of code unreachable.

JUnit Test Cases #Before and #After annotations

We are following below practices to write JUnit tests for our methods.
Each method will be having their own class which holds all the tests which are required for that method. For e.g.: class test {...}
#Before will consists of per-requisites setup for methods like "Entity" so that when we do Edit we don't need to copy/paste code for adding an entity at each method level.
Now here my question is, shall we delete all the data which we entered by writing code to trash test-data in #after method or just let it be?
I know we can make it configurable but what is best practice? keep it or delete it. As per my gut feeling deleting should be better as if there is some duplicate data already in db - it may trigger wrong true or false.
It depends on how much you adhere to the Don't Repeat Yourself principle. It's also worth remembering that you have #After called after each #Test and #AfterClass called after all the #Test have run. With this granularity, it should be simple to remove duplication but still split those tasks that should only run at the very end, or after each test.
As a best practice I would recommend to clear your data storage between every test, to guarantee each test is isolated from other tests.
This could be done with the #After method if you want to keep some of the settings alive (from the #BeforeClassfor example). It could also be done in the #Before method for example by overriding variables with a new instance for every test, if you do so you do not need a clean up after the tests.
To clean up your settings of the #BeforeClass method you should use #AfterClass for example to close a Database connection or something simular what only needed to be done once. But this is not needed for every kind of unit test.

How to deal with interdependent JUnit tests?

I have a question about JUnit testing.
Our JUnit suite is testing various functions that we wrote that interact with our memory system.
The way our system was designed, requires it to be static, and therefore initialized prior to the running of the tests.
The problem we are having is that when subsequent tests are run, they are affected by tests prior to it, so it is possible (and likely) that we are getting false positive, or innaccurate failures.
Is there a way to maintain the testing order of our JUnit tests, but have it re-initialize the entire system, as if testing on the system from scratch.
The only option we can think of is to write a method that does this, and call it at the end of each test, but as there are lots and lots of things that need to be reset this way, I am hoping there is a simpler way to do this.
I've seen problems with tests many times where they depend on each other (sometimes deliberately!).
Firstly you need to setup a setUp method:
#Before
public void setUp() {
super.setUp();
// Now clear, reset, etc all your static data.
}
This is automatically run by JUnit before each test and will reset the environment. You can add one after as well, but before is better for ensuring a clean starting point.
The order of your tests is usually the order they are in the test class. But this should never be assumed and it's a really bad idea to base code on that.
Go back to the documentation. If you need more information.
The approach I took to this kind of problem was to do partial reinitialization before each test. Each test knows the preconditions that it requires, and the setup ensures that they are true. Not sure if this will be relevant for you. Relying on order often ends up being a continuing PITA - being able to run tests by themselves is better.
Oh yeah - there's one "test" that's run as the beginning of a suite that's responsible for static initialization.
You might want to look at TestNG, which supports test dependencies for this kind of functional testing (JUnit is a unit testing framework):
#Test
public void f1() {}
#Test(dependsOnMethods = "f1")
public void f2() {}

Categories