Junit test cases for a class that generates text content - junit

I have a class named EmailNotificationContentBuilder. As the name suggest the class is responsible to generate content for an email notification to be sent after a process ends. The notification basically tells whether the process was successful or not, the start time end time and the statuses of the child processes ( in tabular format ). I have following doubts regarding writing Junit test cases for this class:-
Is it required to have a Junit for this class? Since it generates textual content.
If yes then how can I assert the content generated by the class ? Some of the contents are represented in tabular format.

Do you want to make sure it does what it's supposed to do? If yes, then write a test. If you don't care if the code works fine or not, then don't write one.
This is the most typical thing a unit test does: test that the value returned by a method is correct. Get the String it returns, and check that it's what you expect it to be:
#Test
public void shouldReturnTabularData() {
EmailNotificationContentBuilder builder = new EmailNotificationContentBuilder();
String result = builder.build("some input");
assertEquals("title1\ttitle2\nvalue1\tvalue2", result);
}

Related

Collect JSON object in a file when a Junit test fails

I have ~50 JSON arrays as an array of models being plugged into Unit tests to compare resultant configs. Each file looks like this:
0.json
1.json... and so on
[{model1},{model2},{model3}]
I am trying to run unit tests to compare the resultant configs and want to run the tests in a manner that the test itself keeps running and collect the models if an assertion fails and output it to a json file somewhere.
Say, model2 fails, I want to collect model2 into a file output.json as an array
Till now, the code looks like this, even if the test is file by file, its fine, but will save me days of effort:
#Test
public void compareAWithB() throws Exception {
File lbJsonFile1 = new File("src/test/resources/iad_ad3/6.json");
compareAWithBHelper(lbJsonFile1);
}
public void compareAWithBHelper(File lbJsonFile) throws Exception {
Model[] dtos = new ObjectMapper().readValue(lbJsonFile, Model[].class);
for(Model dto : dtos) {
Model model = ModelConverter.apiToDao(dto);
String A = doSomeThing();
String B = doSomething2();
Assert.assertEquals(A,B);
//Required: if assert fails, collect the json object and continue
}
I tried using SoftAssertions in AssertJ, but weirdly, it was not printing out all the json objects OR maybe, I don't really understand the checkThat() method properly.
Tried using collectors.checkThat, couldn't get it to work reliably. This is a production area, so, don't have much room for errors, and wanna reduce the manual effort.
Made another attempt to use collectors as one of the posts on stackoverflow, couldn't get it to work reliably
/*try {
collector.checkThat(A, CoreMatchers.equalTo(B));
} catch (AssertionError error) {
System.out.println(dto.toString());
throw new AssertionError(error.getMessage());
}*/
Can someone please help ?
If you want to gather all assertion errors and not stop at the first error then soft assertions is a good candidate to use. To get started with soft assertions you can follow the guide available here: https://assertj.github.io/doc/#assertj-core-soft-assertions.
collector.checkThat does not come from AssertJ (neither anything from your code samples), it's a bit confusing, I would suggest to write a reproducible test so that people can help more easily.
Alternatively if you are dealing with JSON, you can give a try to addressed by https://github.com/lukas-krecan/JsonUnit which provides first class citizen JSON assertions.
Hope it helps.

Junit: String return for AssertEquals

I have test cases defined in an Excel sheet. I am reading a string from this sheet (my expected result) and comparing it to a result I read from a database (my actual result). I then use AssertEquals(expectedResult, actualResult) which prints any errors to a log file (i'm using log4j), e.g. I get java.lang.AssertionError: Different output expected:<10> but was:<7> as a result.
I now need to write that result into the Excel sheet (the one that defines the test cases). If only AssertEquals returned String, with the AssertionError text that would be great, as I could just write that immediately to my Excel sheet. Since it returns void though I got stuck.
Is there a way I could read the AssertionError without parsing the log file?
Thanks.
I think you're using junit incorrectly here. THis is why
assertEquals not AssertEquals ( ;) )
you shouldnt need to log. You should just let the assertions do their job. If it's all green then you're good and you dont need to check a log. If you get blue or red (eclipse colours :)) then you have problems to look at. Blue is failure which means that your assertions are wrong. For example you get 7 but expect 10. Red means error. You have a null pointer or some other exception that is throwing while you are running
You should need to read from an excel file or databse for the unit tests. If you really need to coordinate with other systems then you should try and stub or mock them. With the unit test you should work on trying to testing the method in code
if you are bootstrapping on JUnit to try and compare an excel sheet and database then I would ust export the table in excel as well and then just do a comparison in excel between columns
Reading from/writing to files is not really what tests should be doing. The input for the tests should be defined in the test, not in the external file which can change - this can either introduce false negatives or even worse false positives (making your tests effectively useless while also giving false confidence that everything is ok because tests are green).
Given your comment (a loop with 10k different parameters coming from file), I would recommend converting this excel file into JUnit Parameterized test. You may want to put the array definition in another class, because 10k lines is quite a lot.
If it is some corporate bureaucracy, and you need to have this excel file, then it makes sense to not write a classic "test". I would recommend just a main method that does the job - reads the file, runs the code, checks the output using simple if (output.equals(expected)) and then writes back to file.
Wrap your AssertEquals(expectedResult, actualResult) with try catch
in catch
catch(AssertionError e){
//deal with e.getMessage or etc.
}
But it not good idea for some reasons, I guess.
And try google something like soft assert
Documentation on assertEquals is pretty clear on what the method does:
Asserts that two objects are equal. If they are not, an AssertionError
without a message is thrown.
You need to wrap the assertion with try-catch block and in the exception handling do Your logging. You will need to make Your own message using the information from the specific test case, but this what You asked for.
Note:
If expected and actual are null, they are considered equal.

Using assertEqual and getElementbyxpath in Junit Selenium

I'm basically writing a testcase to determine if a status shared on Facebook was actually shared. Below is the xpath for getting the text of first post on Facebook. I want to compare it to the status I posted e.g 'Blah'. I've been trying to use AssertEquals but that doesn't seem to be working.
WebElement status = getElement(By.Xpath("//div[#id='pagelet_home_stream']//ul[#id = 'home_stream']//li[1]//span[#class='userContent']")
AssertEquals(status, "Blah");
You need to call element.getText() otherwise you're comparing with a WebElement object rather than a String. Also, it's important that the expected text goes first in the assertEquals(expected, actual) otherwise you get a confusing message when they don't match.
assertEquals("Blah", status.getText());

Guideliness to write junit test cases for if,loop and exception

I'm new to Junit. I want to write test cases for if condition,loops.
Do we have any guidelines or procedure to write test cases for if,loop conditions?
Can anyone explain with an example?
IF Age < 18 THEN WHILE Age <> 18
DO ResultResult = Result +1 AgeAge = Age +1 END
DO Print “You can start driving in {Result} years”
ELSE
Print “You can start driving now!”
ENDIF
You want one test case for each major scenario that your code is supposed to be able to handle. With an "if" statement, there are generally two cases, although you might include a third case which is the "boundary" of the two. With a loop, you might want to include a case where the loop is run multiple times, and also a case where the loop is not run at all.
In your particular example, I would write three test cases - one where the age is less than 18, one where the age is exactly 18, and one where the age is over 18. In JUnit, each test case is a separate method inside a test class. Each test method should run the code that you're testing, in the particular scenario, then assert that the result was correct.
Lastly, you need to consider what to call each test method. I strongly recommend using a sentence that indicates which scenario you're testing, and what you expect to happen. Some people like to begin their test method names with the word "test"; but my experience is that this tends to draw attention away from what CONDITION you're trying to test, and draws attention toward which particular method or function it is that you're testing, and you tend to get lower quality tests as a result. For your example, I would call the test methods something like this.
public void canStartDrivingIfAgeOver18()
public void canStartDrivingIfAgeEquals18()
public void numberOfYearsRemainingIsShownIfAgeUnder18()
From my understanding of writing in junit for java ,we were used to create a source code into different blocks is the code conventional,and used to pass the values as args to the function from the test cases so the values will steps into the block statements ,and passes the test cases .
For example you are having the variable as age by assuming as functionName(int age), for testing you should pass the integer from the test case as functionName(18) it will steps into the statements and will show you the status of the test case.Create test case for a testing class write test case for the functions
UseClass classObj=new UseClass();// it should be your class
#Test
public void testValidateAge() {
classObj.validateAge("20");
assertEquals(200,"");
}
Correct me if 'm wrong :)

JUnit Reports -- Test Method Descriptions

I am trying to see if there is a way to include "descriptive text" in my junit reports by way of javadocs. JUnit 4 doesnt seem to support the 'description' attribute for the #Test annotation like TestNG does.
So far from what I have researched there is only one tool out there called javadoc-junit (http://javadoc-junit.sourceforge.net/). However I could not get this to work since it seems to be incompatible with Junit 4.
What I want is some way to provide a sentence or two of text with my each test method in the JUnit report. JavaDoc is no good since the target audience will have to swtich between JavaDoc and the Junit Report to see documentation and/or test stats.
Anyone know of anything else I could use with minimal effort?
Best,
Ray J
In JUnit 5 there is a way to annotate every test with a #DisplayName. The declared test classes can have text, special characters and emojis.
The declared text on each test is visible by test runners and test reports.
The Javadoc says:
public #interface DisplayName
#DisplayName is used to declare a custom display name for the annotated test class or test method.
Display names are typically used for test reporting in IDEs and build tools and may contain spaces, special characters, and even emoji.
And the User Guide:
import org.junit.gen5.api.DisplayName;
import org.junit.gen5.api.Test;
#DisplayName("A special test case")
class DisplayNameDemo {
#Test
#DisplayName("Custom test name containing spaces")
void testWithDisplayNameContainingSpaces() {
}
#Test
#DisplayName("╯°□°)╯")
void testWithDisplayNameContainingSpecialCharacters() {
}
#Test
#DisplayName("😱")
void testWithDisplayNameContainingEmoji() {
}
}
There's also rather recent solution called Allure. That's a Java-based test execution report mainly based on adding supplementary annotations to the code. Existing annotations include:
custom description: #Description("A cool test")
grouping by features or stories: #Features({"feature1", "feature2"}), #Stories({"story1", "story2" })
marking methods executed inside test case as steps: #Step (works even for private methods)
attachments: #Attachment(name = "Page screenshot", type = "image/png")
See their wiki and example project for more details.
I don't put javadocs in JUnit tests. I usually make the name of the method descriptive enough so it's as good as or better than any comment I could come up with.
I could imagine, that the Framework for Integrated Tests (FIT) would be a nice and clean solution.
What does FIT do?
FIT is a framework that allows to write tests via a table in a Word document, a wiki table or an html table.
Every character outside of a table is ignored by FIT and let you enter documentation, description, requirements and so on.
How does on of these tables look like?
Imagine a function MyMath.square(int) that squares it's input parameter. You have to build a so called Fixture, being an adapter between your MyMath and the following table:
class.with.Fixture.Square
x square()
2 4
5 25
The first column describes input values, the second the expected result. If it's not equal, this field is marked as red.
How does a Fixture look like?
For the given example, this would be the correct fixture:
package class.with.Fixture // Must be the same as in the fist row of the table
public class Square extends Fixture {
public int x; // Must be the same as in the second row
public int square() { // Must be the same as in the second row
return MyMath.square(x);
}
}
Probably, you can use FIT for your requirements.
Feel free to comment my answer or edit your question for more information!