I am writing Junit test cases for one java application.
If I run the test functions individually its running fine.
When I try to run them together its not running properly
Here is JUnit code
public class CultureMachineTestCases{
CultureMachineAssignment testObj=new CultureMachineAssignment ();
HashSet<String> result =new HashSet<String>();
String answer,answer1;
int flagVal;
#Before
public void init() throws IOException{
testObj.insertDataIntoSet();
testObj.addKeywords("video1");
}
#Test
public void testVideo() throws IOException {
result=testObj.search("abcd");
answer=result.toString();
answer1=answer.replaceAll("[^a-z0-9]","");
assertEquals("video1", answer1);
}
#Before
public void initMethod() throws IOException{
testObj.insertDataIntoSet();
testObj.addKeywords("video2");
}
#Test
public void testLenth() throws IOException{
flagVal=testObj.flag;
assertEquals(1, flagVal);
}
}
Here flag is set to one in CultureMachineAssignment file.
Can any one please tell me what I need to do so I can run all the functions inside test file together
#Before annotated method (init()) is called before every test method. You should only have one method annotated with #Before not to get confused.
The code you have implemented in init() should be moved to testVideo() and code from initMethod() should be moved to testLength().
And your init method should look like this to be sure that test class state is the same for all tests:
#Before
public void init(){
answer = null;
answer1 = null;
flagVal = -1;
result = new HashSet<String>();
}
Related
I have a function that I use to detect whether a certain directory path exists. Here's the function:
public boolean isRunningOnSandbox() {
return Files.isDirectory(Paths.get("/mySandbox/cloud/sandbox"));
}
As you can see, it relies on static method isDirectory. In my team, we do not use PowerMock for testing.
So, how can I test this method? I have tried writing a test like:
#Rule
public TemporaryFolder temporaryFolder;
#Test
public void test() throws IOException {
File parent = new File("/");
temporaryFolder = new TemporaryFolder(parent);
temporaryFolder.create();
File folder = temporaryFolder.newFolder("mySandbox", "cloud", "sandbox");
subject.isRunningOnSandbox();
}
But, I get an error
ava.io.IOException: Permission denied
because it doesn't let me create a temporary folder under the root. I am guessing there is a better way to test this code instead of trying to create a folder.
There are many ways to do it, onee of them migh be like the below one.
Assumming that isRunningOnSandbox method is in some class SomeClass, then refactor this class in this way:
public class SomeClass {
public boolean isRunningOnSandbox() {
return Files.isDirectory(Paths.get(getSanboxPath()));
}
protected String getSanboxPath(){
return "/mySandbox/cloud/sandbox";
}
}
and then in your tests inject into this class another directory to which you have access, for example:
public class SomeClassTest {
class SomeClassToTest extends SomeClass{
String folder;
public SomeClassToTest(String folder){
this.folder = folder;
}
#Override
protected String getSanboxPath(){
return folder;
}
}
static String sandboxFolder = "myTestSandobxFolder";
static Path tempDir;
#BeforeClass
public static void createFolder() throws IOException {
tempDir = Files.createTempDirectory(sandboxFolder);
}
#AfterClass
public static void deleteFolder() throws IOException {
Files.delete(tempDir);
}
#Test
public void IsRunningOnSandbox_shouldReturnTrueWhenPathExists() throws IOException {
//given
SomeClass testedObject = new SomeClassToTest(tempDir.toString());
//when
boolean result = testedObject.isRunningOnSandbox();
//then
assertThat(result).isTrue();
}
#Test
public void IsRunningOnSandbox_shouldReturnFalseWhenPathDoesNotExist() throws IOException {
//given
SomeClass testedObject = new SomeClassToTest("/abcdef123");
//when
boolean result = testedObject.isRunningOnSandbox();
//then
assertThat(result).isFalse();
}
}
The function you have shown is not suited for unit-testing: With unit-testing you try to find the bugs in small, isolated software pieces. But, which bugs could be in this example code that are not related to the other components, that is, the Files component, the Paths component and the actual file system?
The potential bugs in your example are about questions like "am I calling the right functions?" or "do I call the functions with proper values for the arguments?" or "do the functions I call return arguments as I expect" or "am I using the path that is also the path found in the file system". This can not be checked with unit-testing, but with integraton-testing.
Imagine you have the wrong path in mind. Then, in your unit-test you would also check against the same wrong path, and your unit-test would succeed. Only when running that test as an integration test on the real file system you could figure out that the path which you had in mind was wrong and did not match the actual path in the file system.
I changed a junit test class to run with Parameterized to test two different implementations of the same interface. Here it is :
#RunWith(Parameterized.class)
public class Stack_Tests {
private Stack<String> stack;
public Stack_Tests(Stack<String> stack) {
this.stack = stack;
}
#Parameters
public static Collection<Object[]> parameters() {
// The two object to test
return Arrays.asList(new Object[][] { { new LinkedStack<String>() }, { new BoundedLinkedStack<String>(MAX_SIZE) } });
}
#Test
public void test() {
...
}
The results are wrong since I changed to Parameterized. Half of the tests fail (the same for the two objects), all of them worked before.
It works without Parameterized like this :
public class Stack_Tests {
private Stack<String> stack;
#Before
public void setUp() throws Exception {
stack = new LinkedStack<String>();
}
#Test
public void test() {
...
}
The complete test class here
As you suggested in the comments, try resetting the stack before every test, since previous tests change it.
You can create a new stack instance before every unit test:
#Before
public void setUp() throws Exception {
stack = stack.getClass().newInstance();
}
Though this has the side effect that your classes must have 0-argument constructors.
Note: If some of your stacks can not have 0-argument constructors, consider invoking the constructor with arguments as per this SO answer. This means that you must provide the constructor types list and its arguments list along with the stack object to the unit test class as parameters. Then you can do:
#Before
public void setUp() throws Exception {
stack = stack.getClass().getDeclaredConstructors(typesList).newInstance(argsList);
}
add :
#Before
public void setUp() throws Exception {
stack.clear();
}
the stack is shared for each test, and your tests modify the stack.
To get a consistent stack for all tests, an alternative approach is to clone the stack before modifying it in a particular test.
#Test public void testPush() {
Stack<String> myStack = (Stack<String>) stack.clone();
myStack.push("hello");
assertFalse(myStack.empty());
}
Thus, every test that modifies the stack should first clone it.
This is a little more cumbersome, but allows to provide more sophisticated stacks as parameters (e.g., ones with some elements to start with).
I have a JUnit test class that has two test methods:
#Test
public void test1() {
// Setup: Create foo1.m
// Exercise
// Tear Down: Delete foo1.m
}
#Test
public void test2() {
// Setup: Create foo2.m
// Exercise
// Tear Down: Delete foo2.m
}
For each method, I would like to make sure that, if the Exercise section fails for any reason, the Tear Down will still run. Note that the Setup and Tear Down code for both test methods are different, so I don't think I can use JUnit's #Before and #After annotations to do what I want.
I could put TRY-CATCH blocks into each test method:
#Test
public void test2() {
// Setup: Create foo2.m
try {
// Exercise
} finally {
// Tear Down: Delete foo2.m
}
}
but that seems ugly. Is there a way to make sure the test-method-specific tear down code in each test method is executed, without using a TRY-CATCH block?
If the setup and teardown are different, you are essentially cramming two different test fixtures into a single file. The sensible answer is to put them in separate files and use the normal annotations. If they have anything in common separate that out into a common abstract class.
Adding multiple setups in the same file can easily result in a situation where it's not clear which instance members are used in which tests, so that maintaining the tests becomes a lot harder than it needs to be.
Update:
I found a better solution, so I include here, the original answer can be found below. I think JUnit 4 rules can be used here:
class PrepareFile implements org.junit.rules.TestRule {
#Retention(RetentionPolicy.RUNTIME)
public #interface FileName {
String value() default "";
}
#Override
public Statement apply(final Statement statement, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
String fileName = description.getAnnotation(FileName.class).value();
File file = new File(fileName);
try {
file.createNewFile();
statement.evaluate();
} finally {
file.delete();
}
}
};
}
}
Using it in the test:
#Rule
public PrepareFile prepareFile = new PrepareFile();
#Test
#PrepareFile.FileName("foo1.m")
public void test1() {
// Exercise
}
#Test
#PrepareFile.FileName("foo2.m")
public void test2() {
// Exercise
}
Here comes my original answer:
You may try to use the #BeforeClass and #AfterClass annotations.
#BeforeClass
public static void setUp() {
// Setup1: Create foo1.m
// Setup2: Create foo2.m
}
#AfterClass
public static void tearDown() {
// Tear Down1: Delete foo1.m
// Tear Down2: Delete foo2.m
}
#Test
public void test1() {
// Exercise
}
#Test
public void test2() {
// Exercise
}
This way you can setup and tear down all test cases once and the framework ensures that teadDown() is called in case of errors as well.
I am running some JUnit tests programatically with JUnitCore, and I want to get some data out of the test class once it is finished (so #AfterClass). Here is a pseudocode example of the constraints I am working under:
public class A {
public static String testData;
public static void runTest() {
JUnitCore juc = new JUnitCore();
juc.run(B);
// This is where I would like to access testData for this
// particular run
}
public static void setTestData(String s) {
testData = s;
}
}
public class B {
// Some #Test methods and stuff omitted
#AfterClass
public static void done(String s) {
A.setTestData(someData);
}
}
My problem is that different threads might be calling runTest(), so testData might be wrong. How do I work around this? I'm so lost.
If you really need/want to go with this design, you can make testData a java.lang.ThreadLocal<String>. This will solve the multi-threading issue.
I have the following code for JUnit testing:
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
public class JUnitHelloWorld {
protected String s;
#Before
public void setup() {
s = "HELLO WORLD";
}
#Test
public void testHelloWorldSuccess() {
s = s.toLowerCase();
assertEquals("hello world", s);
}
// will fail even if testHelloWorldSuccess is called first
#Test
public void testHelloWorldFail() {
assertEquals("hello world", s);
}
}
Now, according to the comment, why will the second method fail even if the first method is called first? isn't the first method changing the value of s to lowercase?
#Before happens before each test. This means the order you run them in does not matter as it will always perform the setup then do the test.
The tag #BeforeClass will give you the behaviour you are expecting. This runs once before any of your tests start.
JUnit does not run each test case (method with #Test) in order of your code. That is why each test case must be independent of each other.
Also setup method with #Before tag will always get run before each of your test method.
So likelihood (but not necessarily) the order of execution of your code are:
setup()
testHelloWorldSuccess()
setup()
testHelloWorldFail()
But it might also run:
setup()
testHelloWorldFail()
setup()
testHelloWorldSuccess()
for JUnit , the order of testcase execution is not fixed. It may happen that you wrote a method m2 after method m1 and while execution, m2 gets executed first. The best approach is your test case should not be based on the testcase execution order.
try #BeforeClass if you want something to be executed once for the whole class only.
For the above scenario try this:
protected String s;
private int flag ;
#BeforeClass
public beforeClass(){
flag = 0;
}
#Before
public void setup() {
s = "HELLO WORLD";
}
#Test
public void testHelloWorldSuccess() {
flag = 1;
s = s.toLowerCase();
assertEquals("hello world", s);
}
// won't fail even if testHelloWorldSuccess is called first
#Test
public void testHelloWorldFail() {
if(flag == 1)
assertEquals("hello world", s);
else
assertEquals("HELLO WORLD", s);
}