JUnit testing result of a program - java

This is a very basic question for JUnit testing. I wrote a program which calculate the new position of a dot by given instructions for moving. The program is working properly but I have to write a JUnit test for check the result and I don't know how.

Write a test method for every dot movement that you want to check. In each test method you call your method and then compare the actual result with the expected result.
Try something like this, using JUnit 4.x :
package org.dotmover;
import org.junit.Assert;
import org.junit.Test;
public class DotMoverTest {
#Test
public void testDotMoverForward() {
final DotMover dotMover = new DotMover(...);
final int newPos = dotMover.move(...);
final int expectedNewPos = ...;
Assert.assertEquals(expectedNewPos, newPos);
}
}

Add JUnit to classpath of you project. The create JUnit testcase. It is just a class that extends TestCase.
If you are using JUnit prior to v 4.0 each test method must start from word test, e.g.
testPosition(), testMoviing() etc.
If you are using version 4 and higher the test methods must be targeted with annotation #Test.
Now write your testing scenario. User static assertXXX() methods of class Assert to verify that your program is working.
Good luck and happy TDD!

Related

Is there a way to find the ignored JUnit Test with the most lines of code in a large codebase?

This is a static analysis question. It might be possible to write an AST parser with the ANTLR plugin in Checkstyle - or the backend to Findbugs. I'm looking for a pre-existing solution.
We have a weekly meeting of our developers in which we talk about issues of the day. Part of this is looking at the code quality reports in Sonar.
We have a number of ignored JUnit tests we're working through - and I'd like to rank them by size (lines of code in the JUnit test method).
My question is: Is there a way to find the ignored JUnit Test with the most lines of code in a large codebase?
Here is an example of an ignored method in a JUnit test:
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;
public class TestJunit {
String message = "Robert";
MessageUtil messageUtil = new MessageUtil(message);
#Ignore
#Test
public void testPrintMessage() {
System.out.println("Inside testPrintMessage()");
message = "Robert";
assertEquals(message,messageUtil.printMessage());
}
#Test
public void testSalutationMessage() {
System.out.println("Inside testSalutationMessage()");
message = "Hi!" + "Robert";
assertEquals(message,messageUtil.salutationMessage());
}
}
Here is the documentation for the #Ignored annotation.
https://www.tutorialspoint.com/junit/junit_ignore_test.htm
Assumptions:
Simple line-count - counting whitespace is fine. (If a more sophisticated line-count is available that's great - but all I want is a consistent baseline for comparison).
#Ignored can apply to classes and methods - ideally I want both, but this question was originally about ignored methods - so I'll stick with that.
If you use the maven surefire reports plugin to collect all the test reports, actually the ignored tested are collected by default, just like the below screenshots show, and you can go through all the ignored tests details.

How to change the #Test method dynamically in TestNG

This is more of a question on test automation framework design. Very hard indeed to summarize whole question in one line :)
I am creating a test automation framework using Selenium. Mostly I am accessing the data (methods name) from an excel file.
In my main Runner class I am getting a list of test cases. Each test case has a set of methods (can be same or different) which I have defined in a java class and executing each method using java reflection api. Everything is fine till this point.
Now I want to incorporate TestNG and reporting/logging in my automation suite. Problem is I cant use #Test for each method as TestNG considers #Test = 1 Test Case - but my 1 Test case might have more than 1 methods. My methods are more like a test steps for a test case, reason is I dont want repeat the code. I want to create a #Test dynamically calling different sets of methods and executing them in Java Or defining each teststeps for a #Test. I was going through the TestNG documentation, but could not able to locate any feature to handle this situation.
Any help is really appreciated and if you have any other thoughts to handle this situaton I am here to listen.
Did you try the following?
#Test(priority = 1)
public void step1() {
//code
}
#Test(priority = 2)
public void step2() {
//code
}
You need to use "priority" for each method, otherwise it won't work.

Can I run JUnit tests in a random order in IntelliJ IDEa? [duplicate]

I have the classical structure for tests, I have a test suite of different suites like DatabaseTests, UnitTests etc. Sometimes those suites contains other suites like SlowDatabaseTests, FastDatabaseTests etc.
What I want is to randomize the running order of tests so I will make sure they are not dependent to each other. Randomization should be at every level, like suite should shuffle test class order, and test class should shuffle test method order.
If it is possible to do this in Eclipse that will be the best.
You do have a Sortable but I can't see how you would use it.
You could extend BlockJUnit4ClassRunner and have computeTestMethods() return a randomized copy of super.computeTestMethods(). Then use the #RunWith to set that as the runner to use.
e.g.
package com.stackoverflow.mlk;
import java.util.Collections;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;
public class RandomBlockJUnit4ClassRunner extends BlockJUnit4ClassRunner {
public RandomBlockJUnit4ClassRunner(Class<?> klass)
throws InitializationError {
super(klass);
}
protected java.util.List<org.junit.runners.model.FrameworkMethod> computeTestMethods() {
java.util.List<org.junit.runners.model.FrameworkMethod> methods = super.computeTestMethods();
Collections.shuffle(methods);
return methods;
}
}
Then
#RunWith(com.stackoverflow.mlk.RandomBlockJUnit4ClassRunner.class)
public class RandomOrder {
#Test
public void one() {
}
#Test
public void two() {
}
#Test
public void three() {
}
}
https://github.com/KentBeck/junit/pull/386 introduces some orders but not RANDOM. Probably you do not really want this; tests should run deterministically. If you need to verify that different permutations of tests still pass, either test all permutations; or, if this would be impractically slow, introduce a “random” seed for shuffling that is determined by an environment variable or the like, so that you can reproduce any failures. http://hg.netbeans.org/main/file/66d9fb12e98f/nbjunit/src/org/netbeans/junit/MethodOrder.java gives an example of doing this for JUnit 3.
In general what you need to do is to write your own test runner and in the test runner class aggregate the methods and randomly run each test (make sure you don't run a test twice).
Read more about the test framework and how to write your own test runner here:
http://www.ddj.com/architect/184415674
In JUnit 4.13, to run the tests within a test class in random order, write a small helper class:
import org.junit.runner.manipulation.Ordering;
import java.util.Random;
public class RandomOrder implements Ordering.Factory {
#Override
public Ordering create(Ordering.Context context) {
long seed = new Random().nextLong();
System.out.println("RandomOrder: seed = " + seed);
return Ordering.shuffledBy(new Random(seed));
}
}
Then, annotate your test class with:
#OrderWith(RandomOrder.class)
This way, the test methods of this one class are run in random order. Plus, if they unexpectedly fail, you know the random seed to repeat exactly this order.
I don't know though how to configure this for a whole project or a test suite.
I will make sure they are not dependent to
each other
You should make sure that this is the case without relying on random execution order. What makes you fear that dependencies may exist?
This issue is open on JUnit GitHub since 2 years, and point out 2 independent issues:
- Tests depending on the execution order;
- Non repeatable tests.
Consider adressing the issue at the root, rather than trying to use the framework to do the job afterwards. Use setUp and tearDown method to guarantee isolation, and test at the smallest level.
Here is a solution with Gradle and JUnit 5.8.0
Step 1 : Ensure that you have latest JUnit version dependency.
Step 2 : Define the required properties under build.gradle test section
test {
useJUnitPlatform()
systemProperties([
//Random in method level
'junit.jupiter.testmethod.order.default': 'org.junit.jupiter.api.MethodOrderer$Random',
// Random in class level
'junit.jupiter.testclass.order.default' : 'org.junit.jupiter.api.ClassOrderer$Random',
// Log configuration to see the seed
'java.util.logging.config.file' : file('src/test/resources/logging.properties')
])
//To print the JUnit logs in console
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
}
}
Step 3: Define logging.properties under src/test/resources
.level=CONFIG
java.util.logging.ConsoleHandler.level=CONFIG
org.junit.jupiter.api.ClassOrderer$Random.handlers=java.util.logging.ConsoleHandler
org.junit.jupiter.api.MethodOrderer$Random.handlers=java.util.logging.ConsoleHandler
Step 4 : Run test. gradlew clean test
You can see the seed used for the random test in the console
CONFIG: ClassOrderer.Random default seed: 65423695211256721
CONFIG: MethodOrderer.Random default seed: 6542369521653287
In case of flaky test, you can reproduce it by configuring the same seed where the JUnit tests were failing
systemProperties([
'junit.jupiter.execution.class.order.random.seed' : '65423695211256721'
'junit.jupiter.execution.order.random.seed' : '6542369521653287'
])
References : how-to-randomize-tests-in-junit , Random

A Parameterized Parameterized test or Parameterized Suite with a before and after

I have an #Parameterized JUnit test which all works. Now I'm trying to create a new test that runs that same #Parameterized test once for 20 database configurations.
Been having a look online and there are various people who have asked for this but there doesn't seem to be a satisfactory solution. I had a look at Suite but it can't run Parameterized test and it doesn't have any annotations that can be run in between the suite tests to prepare for the next suite test.
Standard Parameterized class:
#RunWith(Parameterized.class)
public class MyParameterizedTest {
// works as normal
}
Here is some pseudo code of what I am looking for:
#RunWith(RunParameterizedLots.class)
#ParameterizedClassToTest(MyParameterizedTest.class)
public class RunParameterizedLotsOfTimes<T> {
#ListOfTestStuff
public List<T> getList() {
return list of T;
}
#BeforeRunningMyParameterizedTest
public void beforePtest(T i) {
setupDatabaseConfig(i);
}
#AfterRunningMyParameterizedTest
public void afterPtest() {
teardownDatabaseConfig(i);
}
}
None of this is written I have spent 2 days reading JUnit documentation and don't seem to be any closer. Release notes for 4.12 talk about #UseParametersRunnerFactory which looks like it might help, there is also some stuff with the new BlockJUnit4ClassRunnerWithParameters but there doesn't seem to be any example of how to use it.
I could create a "#RunWith(Parameterized.class)" class that feeds 1,2,3,4 into itself but then how to I link the sub-parameterized tests into the JUnit subsystem so it looks nice and provides sensible display.
I hope you can see from my waffle question what I am trying to do I just don't know where to start or if someone else has done this work already?
Out of the box it's not possible to parameterize a JUnit test suite, because both are Runners and you may only have one #RunWith() annotation at your test.
For that cause I wrote a new Runner that combines the functionality of both to a ParameterizedSuite: https://github.com/PeterWippermann/parameterized-suite
Good news is, it also enables you to use #Before and #After!
However, I'm not sure if your problem isn't somewhat different: Don't you have two parameters? You say, you already have a parameterized test and now you wan't to run that test against a list of database configurations. So that would be your second parameter. You would like to test all combinations of those two parameters, wouldn't you?

JUnit #Test expected annotation not working

I've got the following test:
#Test(expected = IllegalStateException.class)
public void testKey() {
int key = 1;
this.finder(key);
}
But JUnit reports, that the test fails, although it throws — as expected — an IllegalStateException.
Do I have to configure something else to make this run?
I run the test now with
#RunWith(Suite.class)
#SuiteClasses(Test.class)
public class TestSuite {
}
like in this question, but am still not getting the desired result.
And when I remove the test prefix I'm still getting an error.
I gotta say that I run these tests with Eclipse, but it's configured to use the JUnit 4 Runner.
The problem was, that the class in which the test was nested was an extension of TestCase. Since this is JUnit 3 style, the annotation didn't work.
Now my test class is a class on its own.
#RunWith(JUnit4.class)
public class MyTestCaseBase extends TestCase
I also had problems with #Test(expected = ...) annotation when I extended TestCase class in my base test. Using #RunWith(JUnit4.class) helped instantly (not an extremely elegant solution, I admit)
i tried this one, and work perfectly as expected.
public class SampleClassTest {
#Test(expected = ArithmeticException.class )
public void lost(){
this.lost(0);
}
private void lost(int i) throws ArithmeticException {
System.out.println(3/i);
}
}
also ensure that junit4 is added as dependancy, # (annotations) are new feature in junit 4.
I faced same issue, solution is simple "Don't extends TestCase class"
No, this JUnit test should work as it is - there is nothing more needed on this side.
What makes you sure that the test throws an IllegalStateException? Is it possible that it gets wrapped into another exception of different type?
Please post the exact failure message from JUnit.
As #duffymo suggested, it is easy to verify what (if any) exception the test really throws.
I had the same problem I just changed my imports statements.
I removed :
import org.junit.jupiter.api.Test;
import junit.framework.TestCase;
and added :
import org.junit.Test;
And it worked fine for me.
This looks correct to me.
Check your assumptions. Are you sure it throws the exception? If what you say is true, removing the expected from the annotation should make it fail.
I'd be stepping through the code with a debugger to see what's going on. I'll assume you have an IDE that will do so, like IntelliJ.
Just tested this under JUnit4: this DO work, test completes successfully. Look if it is a IllegalSelectorException or such.

Categories