How to add test method's comment sections from IntelliJ automatically? - java

I am creating test classes from the IntelliJ automatically like following
This gives me the test class as following in the related module accordingly:
public class MyClassTest {
#Test
public void myMethod() {
}
}
What I am looking for is that
Does IntelliJ can automatically insert Given When Then comment sections into test methods?
I am searching for something like following:
public class MyClassTest {
#Test
public void myMethod() {
// Given
// When
// Then
}
}
These sections are useful for the reader coming after some times passed but usually missed while writing test methods. I am looking for a solution to add this behavior to IDE.

Of course. Navigate to Settings - Editor - File and Code templates - JUnit Test Method

Related

TestNG nested tests or test steps

I'm wondering is it possible to make TestNG show in it's report something like nested tests or test steps.
The thing is that I have pretty big integration test cases and it would be nice if I could decouple it on some steps, say, with something like allure's #Step annotation.
For now the test case is shown as one huge separate entry in intellij IDEA report with a lot of logs which is very difficult to go through and analyze.
You can use createNode method of ExtentTest class. it will creating node under main test.
I've never tried to use Inner TestNG classes but that might be possible and I do believe IntelliJ would render the nested view. You could make a simple little project to try it out. There is a guy who seems to have tried inner classes here: http://makeseleniumeasy.com/2018/05/13/testng-tutorials-12-how-to-run-inner-testng-class-from-testng-xml/ . Let me know if it works. Won't know if IntelliJ renders the nesting until you try.
Bonus: If that works, would be interesting to execute your TestNG using Gradle testng plugin and see if HTML report also renders the nesting.
Inner classes can be used to form groups. For one level of nesting the inner classes must be made public.
Try the following:
public class foo {
public class bar1 {
#Test
public void test11() {System.out.println("test11");}
#Test
public void test12() {System.out.println("test12");}
}
public class bar2 {
#Test
public void test21() {System.out.println("test21");}
#Test
public void test22() {System.out.println("test22");}
}
}
JUnit does have #Nested to group them and you can use the shortcut cmd+R etc. to run them, especially if you have lots of test cases
For TestNG, either split them into different (inner) classes, or use structure view in IntelliJ (https://www.jetbrains.com/help/idea/viewing-structure-of-a-source-file.html)
Right-click all those tests that you want to run
Now you can use groups feature of TestNG E.g.:
class RecordsAccessorTest {
#BeforeMethod(groups = "NewRecordGroup")
public void setUp() {
// some set up for only new record creation is tested
}
#Test(groups = "NewRecordGroup")
public void testNewRecordCreation_happyPath() {...}
#Test(groups = "NewRecordGroup")
public void testNewRecordCreation_errorPath() {...}
#Test
public void someOtherTestNotInGroup() {...}
}

JUnit: is it possible to create a Test Suite that executes all test of classes that share a naming convention?

I am aware that I can make a TestSuite enumerating all the classes that I want, for example:
#RunWith(Suite.class)
#SuiteClasses({SQLServerTests1.class, SQLServerTest2.class, ... })
public class AllSQLServerTests {}
However I have almost 100+ classes and I don't want to have to remember to include any new one in the #SuiteClasses annotation.
As my classes have a naming convention (starting with "SQLServer" for example) I am searching for a way to do something like this:
#RunWith(Suite.class)
#SuiteClasses(prefix="SQLServer")
public class AllSQLServerTests {}
is it possible with plain JUnit? with spring or any other framework?
Tag'em
You can add many tags to each test or test class:
#Test
#Tag("red")
#Tag("production")
public void testWithColour() {...}
#RunWith(JUnitPlatform.class)
#IncludeTags("red & !production")
public class JUnit5Example {
//...
}
You can also use #ExcludeTags but it cannot co-exist with #IncludeTags
Run all in test package
#RunWith(JUnitPlatform.class)
#SelectPackages("com.acme.megaproduct.slowtests")
public class JUnit5Example {
//...
}
Write custom Test Runner
Perhaps none of the above can acommodate your needs, in which case you can add custom filtering by writing your own runner.
See here for step by step how to do it.
Then you just use it like:
#RunWith(MyCustomRunner.class)
public class CustomTestSuite {
//...
}

Java template for a project in Eclipse

Is it possible to make creation of (Java) file(s) in Eclipse easier/quicker.
I know there is that "Create new class wizard", but it is slow for my "special" needs...
I have a specific project in which I'm creating new classes often, but the structure for those classes is the same. Let say I want to create class A, so I want file A.java to be created as
class A {
public static void main(String[] args) {
}
static int solve() {
}
}
and it would be perfect that also ATest.java is created for this class, for example
class ATest {
#Test
int test1() {
Assert.assertEquals(0, A.solve());
}
}
or is there such plugin for Eclipse?
Yes, you can try using FastCode Plugin, where you can create new templates as per your requirement. As FastCode plugin supports custom templates, here is an example how to create the above class and test class together:
<template name="CREATE_NEW_CLASS">
<description>Used to Create class in the specified package.</description>
<allowed-file-names>*.*</allowed-file-names>
<first-template-item>package</first-template-item>
<second-template-item>none</second-template-item>
<additional-parameters>className</additional-parameters>
<template-body>
<![CDATA[
<fc:class type="class" name="${className}" package="${package.name}" project="${package.javaProject}">
public class ${className} {
public static void main(String[] args) {
}
static int solve() {
}
}
</fc:class>
<fc:class type="test" name="${className}Test" package="${package.name}" project="${package.javaProject}">
public class ${className}Test {
#Test
int test1(){
Assert.assertEquals(0, ${className}.solve());
}
}
</fc:class>
]]>
</template-body>
</template>
Once you add the template, you need to do import using import option in template preference page as explained in the document.
Yes, this is relatively simple to set up. Open the Project Properties and navigate to the Java Code Style > Code Templates section. Once there, check the box to enable project-specific settings. The generation template you want is under the Code part of the tree; you want Class Body. It is probably empty, but click the Edit... button to modify it.
Whatever you enter in the Edit dialog will be inserted between the class' brackets when using the New Class wizard.
There's no way I know of to automatically create another class (the Test in your case). But Eclipse has a JUnit wizard that makes doing so very easy. Just right-click on a class and choose New > Other... and then find Junit Test Case in the list. That wizard will guide you through creating the test class, including selecting the method(s) you want to test.
Note: these instructions set up the template for just the project or projects you select. You could also set up the same thing for your entire workspace Preferences, but doing so provides no way to share that configuration so that the same project checked out into another workspace will use it. I usually recommend making these kinds of settings on a per-project basis.
I'm not sure you need an IDE-specific template for that. When I was going through Project Euler, I had a setup like this:
public interface Problem {
public Object solve();
}
public class MyProblem implements Problem {
#Override
public Object solve() {
// do some stuff
return result;
}
}
Then in your (JUnit?) tests, you could use
Assert.assertEquals(expected, myProblemInstance.solve());
You can see my implementation here
If you do use an IDE template, you won't be able to use a generic solve() method, since it is not guaranteed that that class has that method. I would highly recommend using interfaces.

How do I make a junit white list of tests to run

I'm working on writing unit tests for a class that I'm developing. Another developer is developing other tests for the same class for methods that he's developing. So our tests find themselves in the same JUnit test class.
So what I wanted to do was to set up a test suite to run just my tests while I'm developing as a temporary measure. I created a Category for my tests and have marked them as such. I then created a class to be my test suite. I told it to include tests that belong to this category. When I run it, it still runs everything. There are a lot of tests, so it would be tedious to mark all the tests I don't want ran with #Ignore. Is there a way to say, run only the tests in a category but none else?
You can write a wrapper test class which method calls the main test class (only your method), then run Junit tests on the wrapper class.
public class MainTestClass {
#Test
public void yourFirstTest() {
...
}
#Test
public void yourSecondTest() {
...
}
#Test
public void otherFirstTest() {
...
}
}
public class WrapperTestClass {
#Test
public void yourFirstTest() {
new MainTestClass().yourFirstTest();
}
#Test
public void yourSecondTest() {
new MainTestClass().yourSecondTest();
}
}
I think you can implement your own 'org.junit.runner.RunWith' and then annotate your test class to use it as necessary.
#RunWith(MyRunnerClass.class)
Note: The correct solution here is in the above comments regarding code branches etc.

Can I specify a class wide group on a TestNG test case?

I have a base class that represents a database test in TestNG, and I want to specify that all classes extending from this class are of a group "db-test", however I have found that this doesn't seem possible. I have tried the #Test annotation:
#Test(groups = { "db-test" })
public class DBTestBase {
}
However, this doesn't work because the #Test annotation will try to make a bunch of methods into tests, and warnings/errors pop up in eclipse when the tests are run.
So I tried disabling the test, so at least the groups are assigned:
#Test(enabled = false, groups = { "db-test" })
public class DBTestBase {
}
but then any #BeforeTest (and other similar annotations) ALSO get disabled... which is of course not what I want.
I would like some way to annotate a class as being of a particular type of group, but it doesn't quite seem possible in TestNG. Does anyone have any other ideas?
TestNG will run all the public methods from a class with a #Test annotation. Maybe you could change the methods you don't want TestNG to run to be non-public
The answer is through a custom org.testng.IMethodSelector:
Its includeMethod() can exclude any method we want, like a public not-annotated method.
However, to register a custom Java MethodSelector, you must add it to the XMLTest instance managed by any TestRunner, which means you need your own custom TestRunner.
But, to build a custom TestRunner, you need to register a TestRunnerFactory, through the -testrunfactory option.
BUT that -testrunfactory is NEVER taken into account by TestNG class... so you need also to define a custom TestNG class :
in order to override the configure(Map) method,
so you can actually set the TestRunnerFactory
TestRunnerFactory which will build you a custom TestRunner,
TestRunner which will set to the XMLTest instance a custom XMLMethodSelector
XMLMethodSelector which will build a custom IMethodSelector
IMethodSelector which will exclude any TestNG methods of your choosing!
Ok... it's a nightmare. But it is also a code-challenge, so it must be a little challenging ;)
All the code is available at DZone snippets.
As usual for a code challenge:
one java class (and quite a few inner classes)
copy-paste the class in a 'source/test' directory (since the package is 'test')
run it (no arguments needed)
Update from Mike Stone:
I'm going to accept this because it sounds pretty close to what I ended up doing, but I figured I would add what I did as well.
Basically, I created a Groups annotation that behaves like the groups property of the Test (and other) annotations.
Then, I created a GroupsAnnotationTransformer, which uses IAnnotationTransformer to look at all tests and test classes being defined, then modifies the test to add the groups, which works perfectly with group exclusion and inclusion.
Modify the build to use the new annotation transformer, and it all works perfectly!
Well... the one caveat is that it doesn't add the groups to non-test methods... because at the time I did this, there was another annotation transformer that lets you transform ANYTHING, but it somehow wasn't included in the TestNG I was using for some reason... so it is a good idea to make your before/after annotated methods to alwaysRun=true... which is sufficient for me.
The end result is I can do:
#Groups({ "myGroup1", "myGroup2"})
public class MyTestCase {
#Test
#Groups("aMethodLevelGroup")
public void myTest() {
}
}
And I made the transformer work with subclassing and everything.
It would seem to me as the following code-challenge (community wiki post):
How to be able to execute all test methods of Extended class from the group 'aGlobalGroup' without:
specifying the 'aGlobalGroup' group on the Extended class itself ?
testing non-annotated public methods of Extended class ?
The first answer is easy:
add a class TestNG(groups = { "aGlobalGroup" }) on the Base class level
That group will apply to all public methods of both Base class and Extended class.
BUT: even non-testng public methods (with no TestNG annotation) will be included in that group.
CHALLENGE: avoid including those non-TestNG methods.
#Test(groups = { "aGlobalGroup" })
public class Base {
/**
*
*/
#BeforeClass
public final void setUp() {
System.out.println("Base class: #BeforeClass");
}
/**
* Test not part a 'aGlobalGroup', but still included in that group due to the class annotation. <br />
* Will be executed even if the TestNG class tested is a sub-class.
*/
#Test(groups = { "aLocalGroup" })
public final void aFastTest() {
System.out.println("Base class: Fast test");
}
/**
* Test not part a 'aGlobalGroup', but still included in that group due to the class annotation. <br />
* Will be executed even if the TestNG class tested is a sub-class.
*/
#Test(groups = { "aLocalGroup" })
public final void aSlowTest() {
System.out.println("Base class: Slow test");
//throw new IllegalArgumentException("oups");
}
/**
* Should not be executed. <br />
* Yet the global annotation Test on the class would include it in the TestNG methods...
*/
public final void notATest() {
System.out.println("Base class: NOT a test");
}
/**
* SubClass of a TestNG class. Some of its methods are TestNG methods, other are not. <br />
* The goal is to check if a group specify in the super-class will include methods of this class. <br />
* And to avoid including too much methods, such as public methods not intended to be TestNG methods.
* #author VonC
*/
public static class Extended extends Base
{
/**
* Test not part a 'aGlobalGroup', but still included in that group due to the super-class annotation. <br />
* Will be executed even if the TestNG class tested is a sub-class.
*/
#Test
public final void anExtendedTest() {
System.out.println("Extended class: An Extended test");
}
/**
* Should not be executed. <br />
* Yet the global annotation Test on the class would include it in the TestNG methods...
*/
public final void notAnExtendedTest() {
System.out.println("Extended class: NOT an Extended test");
}
}
I'm not sure how the annotation inheritance works for TestNG but this article may be of some use.
Actually, this may help better, look at inheritGroups.
You can specify the #Test annotation at method level that allows for maximum flexibility.
public class DBTestBase {
#BeforeTest(groups = "db-test")
public void beforeTest() {
System.out.println("Running before test");
}
public void method1() {
Assert.fail(); // this does not run. It does not belong to 'db-test' group.
}
#Test(groups = "db-test")
public void testMethod1() {
Assert.assertTrue(true);
}
}
Does this works for you or I am missing something from your question.

Categories

Resources