I have suite of fitnesse test cases from junit. and I would like to log the test or page name(from setup()) for each test case. Please let me know how I can find test or page name dynamically with sample code.
Thanks
JUnit's TestName rule is what you're looking for.
public class TestNameTest {
#Rule
public TestName name= new TestName();
#Test
public void testA() {
assertEquals("testA", name.getMethodName());
}
}
Related
I Have a class for which i want to write a Junit unit test case.
public class ComparatorUtil {
public static Map<String, ValueDifference<Object>> compareJsonObject(Object srcObject, Object targetObject)
throws JsonGenerationException, JsonMappingException, IOException {
String initialJson = ConverterUtil.convertObjectToJson(srcObject);
String updatedJson = ConverterUtil.convertObjectToJson(targetObject);
Gson g = new Gson();
Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> firstMap = g.fromJson(initialJson, mapType);
Map<String, Object> secondMap = g.fromJson(updatedJson, mapType);
Map<String, MapDifference.ValueDifference<Object>> diffMap = Maps.difference(firstMap, secondMap).entriesDiffering();
return diffMap;
}
}
public class ConverterUtil {
public static String convertObjectToJson(Object o)
throws JsonGenerationException, JsonMappingException, IOException {
ObjectMapper mapperObj = new ObjectMapper();
return mapperObj.writeValueAsString(o);
}
}
Junit test case written by me:-
#RunWith(PowerMockRunner.class)
#PrepareForTest(ConverterUtil.class)
public class ComparatorUtilTest {
#Before
public void setUp() {
PowerMockito.mockStatic(ConverterUtil.class);
}
#Test
public void testValueDiff() throws JsonGenerationException, JsonMappingException, IOException {
TestObject srcObject = new TestObject();
srcObject.setColor("white");
srcObject.setId(1);
TestObject targetObj = new TestObject();
targetObj.setColor("white");
targetObj.setId(1);
targetObj.setSuffix("AA");
ComparatorUtil.compareJsonObject(srcObject, targetObj);
PowerMockito.verifyStatic(VerificationModeFactory.times(2));
ConverterUtil.convertObjectToJson(srcObject);
ConverterUtil.convertObjectToJson(targetObj);
}
}
When I am running the test class, I am getting a Null Pointer Exception as the initialJson and updatedJson is coming to be null. Can anyone please tell me where am I doing wrong?
So many things so wrong here.
You seem to assume how to use PowerMock. But what you put together simply doesn't make sense! You need to create a mocking specification using 'when().thenReturn()' for example.
Meaning: it is not enough to instruct PowerMock that a certain class will be mocked. You have to tell PowerMock about the actual values to be returned when these static methods are invoked.
so start by reading a good tutorial top to bottom. Don't use PowerMock for your own code, instead look how a tutorial solves a simple problem.
Then: PowerMock comes at certain cost. So you avoid using it. You rather should step back and look into reworking your code so that it can be tested without the need to mock static methods. You see, we are talking about code that transforms some input into some output. You should be able to write production and test code that requires no mocking at all for such situations. If at all, you should use frameworks such as Mockito - good production code can be tested without PowerMock.
More specifically: why is there a need to mock the static method? That seems to indicate that your ObjectMapper doesn't work in your unit test setup. It starts right there!
You see, a good unit test for your conversion method should simply look like:
assertThat(someConverterUnderTest.convert(fineTunedInput), is(expectedOutput));
That's it! You should design your converter to fully work in your unit test environment. And then all need for mocks is gone. In other words: you are currently testing implementation details. Instead you should always try testing the public contract of your methods. Testing implementation details is sometimes unavoidable, but as written before: the code you are showing here should really really be tested without mocks.
Then: even when you need mocks: the static methods are getting in your way. That is a clear signal that you shouldn't be using static here! Instead, you turn those elements that might require mocking either into parameters or into fields of your classes under test. Because then you can simply inject mocked objects. Which means that you don't need the PowerMock(ito) tooling anymore.
From Program Creek on the net.thucydides example sources I found a solution for altering the name of the test in my JUnit class, but it doesn't work. I still get one test name in my report (as shown in the image link)
Only 1 Test
My ultimate goal is to run the same Maven-Serenity JUnit Test multiple times and report the unique Testname feeded by a parameter coming from the spreadSheetData named "testCase"
Maybe my solution doesn't make a change at all, and hopefully it is clear what I want.
Does anyone can help me going forward?
My fragments of code is shown below:
#RunWith(SerenityParameterizedRunner.class)
public class STP_Offer_Flow_Test {
...
public static Collection<Object[]> spreadsheetData() throws IOException {
InputStream spreadsheet = new FileInputStream("src/test/resources/testdata.xlsx");
return new SpreadsheetData(spreadsheet, null).getData();
...
public class AnnotatedDataDrivenScenario
{
private String name;
#Qualifier
public String getQualifier()
{
return name;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
#Test
public void STP_Offer_Flow_Basic() throws Throwable {
log.info(testCase);
log.info("applicantID = " + applicantID);
AnnotatedDataDrivenScenario testCaseAnnotation = new AnnotatedDataDrivenScenario();
testCaseAnnotation.setName(testCase);
...
}
One way to do this is:
#Test
#Title("{0}")
public void myTestMethod(String title){
...
}
What this does is put the title into the #Title. It uses title's toString() method so you can pass any object as long as it's toString() method returns anything that would constitute a title (/String).
You can do more, for example:
#Test
#Title("Test Case no. {1} project {0}.")
public void myTest(Project project, int testCaseNo){
...
}
Title will state something like this:
Test Case no. 3 project MyProject.
EDIT Scratch all that, this solution only works for Serenity's #Step and not #Title that is used with JUnit's test method. Those need not have any parameters passed to them.
I see only one solution and that is JUnit 5 Dynamic Test. Not sure yet how it will go with Serenity BDD. If you have a chance to test this let me know. I'll edit this answer again if I gain any experience with it too.
In JUnit3, one would could name a test suite like this:
public static Test suite() {
TestSuite suite = new TestSuite("Some test collection");
suite.addTestSuite(TestX.class);
return suite;
}
Is there an equivalent way to do this in JUnit4?
Thanks.
EDIT
Thank you, I actually managed to get it working. My question was if there is a JUnit4 equivalent way of specifying the name/description of a test suite, like in JUnit3 with "Some test collection".
Some background:
I'm converting junit tests in legacy code to the version 4, and I don't want to lose any information if possible. I apologize, I should really have been more specific in the original question.
You can do this with the Suite runner #RunWith(Suite.class):
#RunWith(Suite.class)
#SuiteClasses({Test1.class, Test2.class, TestX.class})
public class MySuite {}
Where Test1, Test2, TestX contain your tests
ref. RunWith, Suite
update:
WRT changing the actual description of your suite, I don't think there's a way to do it out-of-the-box (if there is I haven't seen it yet). What you can do, is to define your own runner with a custom description [update2]:
#RunWith(DescribedSuiteRunner.class)
#SuiteClasses({Test1.class, Test2.class, TestX.class})
#SuiteDescription("Some test collection")
public class MySuite {}
public class DescribedSuiteRunner extends Suite {
// forward to Suite
public DescribedSuiteRunner(Class<?> klass, RunnerBuilder builder)
throws InitializationError {
super(klass, builder);
}
#Override
protected String getName() {
return getTestClass()
.getJavaClass()
.getAnnotation(SuiteDescription.class)
.value();
}
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface SuiteDescription {
String value();
}
The default implementation of getName just returns the class being tested's name
Yes, In JUnit 3.x, the JUnit methods had to be specifically named. They needed to begin with the word test in order for JUnit to run that as a test case. Now you can just use the #Test annotation:
#Test
public void thisIsMyTest() {
// test goes here
}
Also in JUnit4 you can state if you want some tests to run before or after all the tests in this class are invoked:
#Before
public void init() throws Exception {
System.out.println("Initializing...");
}
#After
public void finish() throws Exception {
System.out.println("Finishing...");
}
Further comparisons between JUnit3 and JUnit4 here and here.
Edit: after blgt's comment, I see I might have misunderstood your intent.
You are probably looking for #RunWith(Suite.class) - When a class is annotated with #RunWith, JUnit will invoke the class in which is annotated so as to run the tests, instead of using the runner built into JUnit. Full example of usage is here, tl;dr below:
#RunWith(Suite.class)
#SuiteClasses({ FirstTest.class, SecondTest.class })
public class AllTests {
...
}
#RunWith(DataProviderRunner.class)
#RunWith(SpringJUnit4ClassRunner.class)
public class DatabaseModelTest {
// some tests
}
or
#RunWith(Parameterized.class)
#RunWith(SpringJUnit4ClassRunner.class)
public class DatabaseModelTest {
// some tests
}
We can not use two runner property in one test case class...!! so that
I want to run test case with Multiple data how i pass multiple parameter in Rest web service to execute test case ??
Any solution for extend class for DataProviderRunner or parameterized ??
Thanks
(stayconnected52)
You could use Spring's JUnit rules instead of the SpringJUnit4ClassRunner. This works at least with the Parameterized runner. I don't know whether it works with the DataProviderRunner, too.
You need at least version 4.2.0 of the Spring framework and spring-test.
#RunWith(Parameterized.class)
public class DatabaseModelTest {
#ClassRule
public static final SpringClassRule SCR = new SpringClassRule();
#Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
...
}
I tested the solution of #Stefan and works also well for #RunWith(DataProviderRunner.class)
I found a second solution in DataProvider for Spring Integration Testing, they wrote a class DataProviderRunnerWithSpring and set the test class like:
#RunWith(DataProviderRunnerWithSpring.class)
public class TestClass{
...
}
I wanted to know if there's any way to add test suites dynamically in junit 4.
For example I have a TestClassA as mentioned below having test case "test1"
class TestClassA
{
#Test
public void test1()
{
createTestClassDynamically(); // this creates a test class having
// setUp(), tearDown() methods and one test case .
}
}
Test case test1 has a method createTestClassDynamically() that dynamically creates a new test class (lets say TestClassB) having setUp(), tearDown() methods and one test case (lets say test2()).
I want to run the test1 and then when TestClassB is dynamically generated I want test case "test2" also to be executed.
I know this is quite complicated and not the best thing to do but in my framework I need to do it to generate large number of test classes dynamically rather than having them physically in the package.
Can anyone please provide any help/suggestions?
I have solved this is my framework using the Parameterized feature of Junit 4 which helps to execute same test case with different parameters.
Below mentioned is the sample code on how I acheived it, thought to post it if it helps anyone.
Also, if someone has a better solution, feel free to post it.
class TestClassA
{
private TestClassB classBObj;
public TestClassA(TestClassB obj) {
classBObj= obj;
}
#Test
public void test1()
{
// createTestClassDynamically(); // remove this method as Parameterized
// feature will take care of dynamic test execution.
}
#Test
public void test2()
{
// Test case from Test class B using TestClassB object (classBObj)
}
public static Collection<Object[]> getParameters() {
Collection<Object[]> parameteres = new ArrayList<Object[]>();
Object[] obj1 = new Object[]{new TestClassB()};
Object[] obj2 = new Object[]{new TestClassB()};
parameteres.add(obj1);
parameteres.add(obj2);
// ....... add more test data this way or create a loop
return parameteres;
}
}