No. Unit testing is a super set of public static void main. And the best part is that you can have as many as you want. So how great is this, that you can test as many aspects of your program as you want. In days when unit testing was not introduced people had to write nasty logic via main method to do all those testings and even made themselves careful to not choose any objects or primitive names that conflict with each other. Well, not any more. Each part of main is executed under @Test method and they don't interfere with each other (you are a java programmer you may do nasty things to interfere). You can do what ever you did in public static void main like System.out.println and etc. And if you like unit testing a more, you may choose to display none of those output and silently say I assume this is the output, so please verify this for me. Let's see an example.
I had to test this method against many inputs. So if I did this in main, I had to make new variables for each, because array is constant and it does not let me assign to new array at runtime. So to be free of that nuisance lets write two unit tests that don't interfere with each other.
@Before // think this a a constructor, method name don't matter
public void setUp() {
betMon = new BettingMoney();
}
@Test
public void testMoneyMade0() {
int[] amounts = { 10, 20, 30 };
int[] centsPerDollar = { 20, 30, 40 };
int finalResult = 1;
System.out.println("What's up folks");
assertEquals(49000,
betMon.moneyMade(amounts, centsPerDollar, finalResult));
}
}
Every library, every framework, and every stable java code nowadays is tested against this. They have tens of thousands of such methods (actually it is main anyway) in a framework of few hundred methods. They test it with Inter.MAX_VALUE. Double.NAN i.e all the limits, all the odd conditions that a method must pass during real time execution on client code. It is one of the most praised behavior of a programmer to do unit testing (write as many mains as you can), so will you miss any chance to write a main method once and don't have to change any of it to write another execution code. One thing to be careful though unit testing is not integration testing. In unit testing you test the lowest entity with as little or no dependency at all with other parts of the code. What I mean is the method above(moneyMade) is a self testable method. It does not assume or use anything other than the runtime environment provided by java. It does not go into layers or connect to database and test it's variables against that. Such conditions can fail. They require special runtime assumptions. Some server must run, so for those types of method you have to separate the testing code into another directory and say it is integration. If you do so you won't mix up unit testing and integration testing. So always keep it mind is it a unit I am going to test or a whole family of dependencies.
public class BettingMoney {
public int moneyMade(int[] amounts, int[] centsPerDollar, int finalResult) {
int sum = 0;
for (int i = 0; i < amounts.length; i++) {
if (finalResult == i) {
sum -= (centsPerDollar[i] * amounts[i]);
} else {
sum += amounts[i] * 100;
}
}
return sum;
}
}
public int moneyMade(int[] amounts, int[] centsPerDollar, int finalResult) {
int sum = 0;
for (int i = 0; i < amounts.length; i++) {
if (finalResult == i) {
sum -= (centsPerDollar[i] * amounts[i]);
} else {
sum += amounts[i] * 100;
}
}
return sum;
}
}
I had to test this method against many inputs. So if I did this in main, I had to make new variables for each, because array is constant and it does not let me assign to new array at runtime. So to be free of that nuisance lets write two unit tests that don't interfere with each other.
public class BettingMoneyTest {
private BettingMoney betMon;
private BettingMoney betMon;
@Before // think this a a constructor, method name don't matter
public void setUp() {
betMon = new BettingMoney();
}
@Test
public void testMoneyMade0() {
int[] amounts = { 10, 20, 30 };
int[] centsPerDollar = { 20, 30, 40 };
int finalResult = 1;
System.out.println("What's up folks");
assertEquals(3400,
betMon.moneyMade(amounts, centsPerDollar, finalResult));
}
@Test
public void testMoneyMade1() {
int[] amounts = { 200, 300, 100 };
int[] centsPerDollar = { 10, 10, 10 };
int finalResult = 2;
System.out.println("I can do what I did in main here too");
betMon.moneyMade(amounts, centsPerDollar, finalResult));
}
@Test
public void testMoneyMade1() {
int[] amounts = { 200, 300, 100 };
int[] centsPerDollar = { 10, 10, 10 };
int finalResult = 2;
System.out.println("I can do what I did in main here too");
betMon.moneyMade(amounts, centsPerDollar, finalResult));
}
}
Every library, every framework, and every stable java code nowadays is tested against this. They have tens of thousands of such methods (actually it is main anyway) in a framework of few hundred methods. They test it with Inter.MAX_VALUE. Double.NAN i.e all the limits, all the odd conditions that a method must pass during real time execution on client code. It is one of the most praised behavior of a programmer to do unit testing (write as many mains as you can), so will you miss any chance to write a main method once and don't have to change any of it to write another execution code. One thing to be careful though unit testing is not integration testing. In unit testing you test the lowest entity with as little or no dependency at all with other parts of the code. What I mean is the method above(moneyMade) is a self testable method. It does not assume or use anything other than the runtime environment provided by java. It does not go into layers or connect to database and test it's variables against that. Such conditions can fail. They require special runtime assumptions. Some server must run, so for those types of method you have to separate the testing code into another directory and say it is integration. If you do so you won't mix up unit testing and integration testing. So always keep it mind is it a unit I am going to test or a whole family of dependencies.
No comments:
Post a Comment