Need object setup before multiple unit tests are run - java

At the moment I have the following code:
public class AlterServiceSelT
{
#Before
public void setupAndActivate()
{
System.out.println("setupAndActivate");
}
#Test
public void suspendService()
{
System.out.println("suspendService");
}
#Test
public void reActivateService()
{
System.out.println("reActivateService");
}
#After
public void terminateService()
{
System.out.println("terminateService");
}
}
and when ran I get the following in my console:
setupAndActivate
reActivateService
terminateService
setupAndActivate
suspendService
terminateService
The problem is that the full code for setupAndActivate() takes 15 minutes and its output is needed to run for the tests. Ideally I would like the console to output:
setupAndActivate
reActivateService
suspendService
terminateService
How could this be done?

Try looking at #BeforeClass in stead of using the #Before.
One of the downsides of BeforeClass is that it has to be defined on a static method, so all your fields that you set up have to be static.
Upside is that your setup is only done once for all the tests in your class.
Are you sure that a setup of 15 minutes is optimum for your application?

Related

Why does my test run in <1 second in single execution but 20+ seconds in maven build?

I am working on a project with several spring-boot-based integrationtests that take ~5 Minutes to run in total. Upon trying to reduce this runtime i noticed that one very small and simple test takes ~20 seconds. When run "alone" it takes less than a second, which is what I would have expected.
The other tests are all integrationtests with annotations like:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
#MockBean(value = SomeBean.class)
#MockMvcTest
#ContextConfiguration(initializers = someInitializer.class)
But the test in question has no annotations like this, requires no application context and should go through smoothly and quickly according to my understanding. It looks something like this:
public class SomeUnitTest{
#Test
public void testObjectOfClass(){
SomeClass someClass= new SomeClass ("1", "2", "3", "4");
SomeClass.assertThat(someClass).hasId("1-2-3-4");
}
}
Can anyone explain why the tests behave like this. Even if I can't change it I would really apreciate to understand what's going on.
I've seen this before where the JUnit runner is timing it incorrectly.
I had a test that would run sub-second on its own but slow in a full test run. It would run immediately before a test with a bunch of setup with plugins & #BeforeAll steps. After digging into it, I found that the timer was not switching to this next test class until after the setup was completed.
It's possible you're seeing the same thing if the other tests have lots of pre-test setup.
EDIT: #BeforeAll definitely gets timed poorly.
public class TestA {
#Test
public void test() {
}
}
public class TestB {
#BeforeAll
public static void before() throws InterruptedException {
Thread.sleep(10000);
}
#Test
public void test() {
}
}
public class TestC {
#BeforeAll
public static void before() throws InterruptedException {
Thread.sleep(10000);
}
#Test
public void test() {
}
}

How to run specific method before of only specific test cases using TestNG?

In my test class, suppose I've 15 test cases. Out of 15, I require common test data for only 5 test cases. Hence I want to write a method, which will create test data, but that method will execute before any of those 5 tests are run.
I know #BeforClass - which will run before any of tests from the class is run and #BeforeMethod - which will run before every test in the class.
I do not want to use #BeforeClass to create test data for 5 test cases out of 15 because if I want to debug a test which does not belong to those 5 test cases still it will create data, which is not required for my current test, also it will increase execution time.
Is there any way with TestNG, I can run specific method before some of the tests are executed(Without using testng.xml)
TestNG only provides dependency on other test methods. which makes a method to make as a test method.
To Archive what you needed You can do This:
#Test
void testMethod(){
//this is your test method
beforemethod();
}
//your before method for you test-case
void beforemethod(){
}
Hope this fixes you issue
From your description I understand you need a dataProvider (which is exactly that, a method providing same data for Multiple test cases or alternatively multiple data for the same test case).
#DataProvider(name = "dataProviderFor5TestCases")
public Object[][] createData() {
return new Object[][] {
{ "Joe", new Integer(43) },
{ "Mary", new Integer(32)},
};
}
Then you can declare the dataProvider on your test case as such:
#Test(dataProvider = "dataProviderFor5TestCases")
public void testCase1(String name, Integer age) {
System.out.println(name + " " + age);
}
Result will be:
Joe 43
Mary 32
So testCase1 will be executed twice with the set of data created in the dataProvider. However, I think you need the same data for all 5 test Cases (achievable).
Now, regarding execution time. I am not 100% sure but I believe data is created on demand (i.e. if the testCase is skipped or failed no data is created; but I had a very small load so please try it and let us know!)
Update after OP's comment:
So, you are probably better off, using testGroups then which will suit you for both setup before the test and cleanup afterwards (without being invoked for irrelevant test cases):
#Test(groups = { "init" })
public void serverInit() {
startServer();
}
#Test(groups = { "init" })
public void initEnvironment() {
createUsers()
}
#Test(groups = { "cleanup"}, dependsOnGroups = { "init.*" })
public void testCase1() {
//perform your tests
}
#Test(dependsOnGroups = { "cleanup"})
puplic void cleanup(){
deleteUsers();
killServer();
}
The above testCase1 won't be executed if any of the init test method fail (i.e. server fails to start). In addition, cleanup method will only be invoked if the testCase1 succeeded. If you want the cleanup method to be run regardless of testCase1 result you can use alwaysRun like so:
#Test(dependsOnGroups = { "cleanup"}, alwaysRun=true)
Hope that helps!
Best of luck!
Example taken from here:
TestNG DataProvider
You can use dependsOnMethods in #Test() annotation
e.g.
#Test
public void testDataSetup()
{
// Setup your testDataHere
}
#Test(dependsOnMethods = { "testDataSetup" })
public void testExecute1()
{
// Use Your logic here which executes after datasetup
}
For Complete Tutorials see this link

How to run specific junit tests at run time

I'm trying to figure out a good solution to having specific unit tests run with certain runtime configurations. For example:
public class TestClassAlpha() {
#setup
public void setup() {
}
#After
public void tearDown() {
}
#Test
#<only run in particular env>
public void testA() {
//whatever A
}
//always run below test no mater what env
#Test
public void testB() {
//whatever B
}
}
I am contemplating a custom annotation or custom rule perhaps, but i thought this has to be a question that comes up frequently as running tests in certain conditions (envs) is a very valid scenario. I did some limited searching within stack, and I didn't find anything that really that helped solidify either way.
This post shows you exactly what you require.
You should Write a Custom TestRule and an annotation to mark the condition.

Run Junit #Test that ignores #Before/#After

Is it possible to run a JUnit #Test method in a class that has a method annotated with #Before, but to ignore the #Before method only for this test?
Edit: I am interested if JUnit supports this functionality, not workarounds. I am aware of workarounds like moving the test(s) in another class or removing the annotation and manually calling setUp() in each test method.
Suppose in a class there are 30 tests, and for 29 of them #Before really simplifies the testing initialization, but for one (or more than one) of them is useless/it complicates things.
public class MyTestClass {
#Before
public void setUp() {
//setup logic
}
#Test
public void test1() {
//[...]
}
#Test
public void test2() {
//[...]
}
//more tests here
#Test(ignoreBefore = true, ignoreAfter = true //false by default)
//something equivalent to this
public void test20() {
//[...]
}
}
You can do this with a TestRule. See my answer to Exclude individual test from 'before' method in JUnit. Basically, implement ExternalResource, and in the apply method, check if there is a specific annotation on the method, and if there is, don't run the before/after method. You'll have to specifically call the before/after from your rule though.
If it useless it should not be a problem - does it harm to run the setUp once more?
However I don't think it's possible and looks for me as a cripple feature.
Another approach - move that test to a separate test-class.
With JUnit 5 You can have nested tests using #Nested annotation :
public class MainClass {
#Nested
class InnerClass1 {
#BeforeEach
void setup(){}
#Test
void test1(){}
}
#Nested
class InnerClass2 {
// No setup
#Test
void test2(){}
}
}
Just to add to this, something that I found out on a recent visit to this area.
Junit/Mockito seems to give preference to mocking behavior defined in a test, over a #Before annotated method.

Loading configuration only once before a set of test cases

I have a java package which contains all my test case classes. Each class contains a lot of test cases. Each class is loaded and run one by one by JUnit. However each of the classes contains common configuration code which is run again and again and initialised everytime each of the classes are run.
These initializations take a lot of time.
Is there some way to load these configuration changes first and then run the test case so that I do not need to load them everytime.
JUnit4 has #BeforeClass annotation.
Just do something like this:
public class TestClass {
private static SomeConnection connection;
#BeforeClass
public static void setUp() {
//do common setup
connection = new SomeConnection();
}
#Test
public void testSomething() { }
#Test
public void testSomethingElse() { }
#AfterClass
public static void tearDown() {
//do teardown operations
connection.close();
}
}
Method marked with #BeforeClass will run only once. Just make sure you use JUnit4.
Update:
Also note, that it should be static, and as #ChristopheRoussy mentioned, you can use #AfterClass to destroy your common setup.
You can create a static method that is run before the tests within the class are ran.
#BeforeClass
public static void ranOnlyOnce() {
/*...*/
}
Moreover, if you want to run this once before all of your tests, then you should group your tests in a suite, and put this method in this class, and use JUnit to run the suite instead of the tests.
#RunWith(Suite.class)
#SuiteClasses(value = { Test1.class, ... , Testn.class })
public class AllTests {
#BeforeClass
public static void beforeAllTests() {
/*...*/
}
}
Note that annotations can be used only in Junit 4+.
I would recommend grouping your tests into a testsuite and doing the initialization from the testsuite. There is a good discussion of the possibilities here http://www.xoriant.com/blog/software-testing-and-qa/using-customized-junit-testsuite-for-testing.html
There are a number of possibilities. The first and easiest is to use #BeforeClass and #AfterClass as has been suggested by Matyas and jFrenetic. This is the easiest way to do it if none of the test classes share setup code.
If the classes share the same setup and teardown, look at using the TestRule, specifically the ExternalResource, which allows you to run code before and after each class. The difference between this and #BeforeClass and #AfterClass is that it uses the same class, and therefore the code can be shared more easily. This can be done for example:
#RunWith(Suite.class)
#SuiteClasses({A.class, B.class, C.class})
public class UsesExternalResource {
public static Server myServer= new Server();
#ClassRule
public static ExternalResource resource= new ExternalResource() {
#Override
protected void before() throws Throwable {
myServer.connect();
};
#Override
protected void after() {
myServer.disconnect();
};
};
}
This works in a test class as well, so you could have different, but shared setups for different classes.

Categories

Resources