Using assertion in main() method - java

Here is a question I'm trying to answer:
Which of the following use assertions appropriately?
public class Hunt {
public static void main(String... args) {
int y = 10;
assert y > 5; // #1
new Hunt().netant(y);
}
public void netant(int x) {
assert x > 0; // #2
anteater(x);
}
private void anteater(int x) {
assert x > 0; // #3
}
}
Choose: 2
Options:
#1
#2
#3
The program has runtime errors although assertions are used correctly
Correct Answer: 1 & 3
Explanation: It is not advisable to use assertions to assert arguments of public methods
Source:http://www.certpal.com
The answer states "It is not advisable to use assertions to assert arguments of public methods". But in the above code even though assert statement is used to assert arguments of main() method it is chosen as the right answer!
Is it advisable to use assert statement in main() method?

Assertions are a defence mechanism for coding errors. Entering an invalid argument in to a public method is a user error, even if it's an API a programmer is using.
Users should never see an assert, tests should.

It is not advisable to use assertions to assert arguments of public methods. y is not an argument.
public static void main(String... args) {
int y = 10;
assert y > 5; // #1
new Hunt().netant(y);
}
However, the following is not a good practice:
public static void main(String... args) {
assert args.length==42;
}

Assertions should not be used to:
Argument checking in public methods
To do any work that your application requires for correct operation
#1: Check a value of a local variable. Checking the arguments of the main method with assertions is not a correct use but checking a local variable is valid.
#2: Check the parameter of a public method. Invalid use of assertions.
#3: Check the parameter of a private method. The class controls the
parameters used in the method invocation, so this is a valid use.

Related

Calling static method in test class(Junit)

I am writing junit test cases for my project but i am facing one problem
Here is a method that i am using in one of my java class (GraphNodes.java)
public static ArrayList<String> getCSList() {
System.out.println(CSList.size()); // Output : 3
return CSList; // returns 3 elements in list
}
Now here is my test class for Junit
#Test
public void checkCSListCount(){
int actual= GraphNodes.getCSList().size(); // My exceptation here is 3 but in console it shows 0
int excepted = 3;
assertEquals(excepted,actual);
}
My junit is failing by saying excepted<3> but actual<0>
Also i cannot change the static method to only public because it will affect some functionality of the code and since i am new to junit, i am not getting idea how to fix this.so can anyone help me out here
Thanks in Advance!!
You need to validate how you populate the object CSList() during runtime and do exactly the same when you are running the test.
One option is to have a #BeforeEach method in your test where it will set the values of what you need during the test.
#BeforeEach
public void setUp() {
GraphNodes.setCSList(Arrays.asList("A","B","C"));
}
#Test
public void checkCSListCount(){
int actual= GraphNodes.getCSList().size();
int excepted = 3;
assertEquals(excepted,actual);
}
I think you are trying to write an integration test. So you should call the method, that fills the list with your 3 elements, before checking the list size. If all the logic for that is in your main method you should extract it into its own method.

How to validate overall execution of multiple JUnit 4 tests?

Desired: A "Test of the Tests"
Imagine there is some additional "sanity check" that could be performed after a test class completes all its tests that would indicate whether test execution as a whole executed successfully. This final sanity check could possibly use some aggregated information about the tests. Just as a crude example: The number of calls to a shared method is counted, and if the count is not above some minimum expected threshold after all tests complete, then it is clear that something is wrong even if all the individual tests pass.
What I have described is probably in some "grey area" of best practices because while it does violate the doctrine of atomic unit tests, the final sanity check is not actually testing the class being tested; rather, it is checking that test execution as a whole was a success: A "test of the tests," so-to-speak. It is additional logic regarding the tests themselves.
This Solution Seems Bad
One way to accomplish this "test of tests" is to place the sanity check in a static #AfterClass method. If the check fails, one can call Assert.fail(), which actually works (surprisingly, since I presumed it could only be invoked from within methods annotated with #Test, which by nature must be instance methods, not static):
public class MyTest {
[...]
#AfterClass
public static void testSufficientCount() {
if (MyTest.counterVariable < MIN_COUNT) {
Assert.fail("This fail call actually works. Wow.");
}
}
}
There are many reasons why this solution is a kludge:
Assume there are N tests in total (where a "test" is an instance method annotated with #Test). When Assert.fail() is not called in #AfterClass, N tests in total are reported by the IDE, as expected. However, when Assert.fail() is called in #AfterClass, N + 1 tests in total are reported by the IDE (the extra one being the static #AfterClass method). The additional static method was not annotated with #Test, so it should not be counted as a test. Further, the total number of tests should not be a function of whether some tests pass or fail.
The #AfterClass method is static by definition. Therefore, only static members are accessible. This presents a problem for my specific situation; I will leave this statement without elaboration because the explanation is out of the scope of the question, but basically it would be most desirable if only instance members were used.
[Other reasons too...]
Is There a Better Way?
Is there a way to implement this "test of tests" that is considered good and common practice? Does JUnit 4 support adding some kind of logic to ensure a group of unit tests within a class executed properly (failing in some way if they did not)? Is there a name for this thing I have called a "test of tests"?
About variable number of tests
I don't think there is a valid solution ...
About static fields
I tried to follow your example and, if I understood well, with a combination of Verifier, TestRule and ClassRule it is possible to use only the instance fields of the test class
Here my code from which to take a cue:
public class ATest {
public int countVariable = 0;
private static class MyVerifier extends Verifier {
public int count = 0;
#Override
protected void verify() throws Throwable {
assertTrue(count < 1); // cause new failed test
// assertTrue(count >= 1); // it's all ok
}
}
#ClassRule
public static MyVerifier v = new MyVerifier();
private class MyRule implements TestRule {
ATest a;
MyVerifier v;
public MyRule(ATest a, MyVerifier v) {
this.a = a;
this.v = v;
}
#Override
public Statement apply(Statement base, Description description) {
try {
base.evaluate();
this.v.count = a.countVariable;
} catch (Throwable ex) {
Logger.getLogger(ATest.class.getName()).log(Level.SEVERE, null, ex);
}
return base;
}
}
#Rule
public MyRule rule = new MyRule(this, v);
#org.junit.Test
public void testSomeMethod() {
countVariable++; // modifies instance counter
assertTrue(true);
}
#org.junit.Test
public void testSomeMethod2() {
countVariable++; // modifies instance counter
assertTrue(true);
}
}
Having said that
"test of tests" isn't consider a common and good practice because, as you know, it violates at least two of five principles of the FIRST rule(see Cleean code from Uncle Bob Martin): tests must be
F: Fast
I: Indipendent
R: Repeteable
S: Self-validating
T: Timely (linked to TDD practice)

Test method that returns void

I have a void method and I want to test it. How do I do that?
Here's the method:
public void updateCustomerTagCount() {
List<String> fileList = ImportTagJob.fetchData();
try {
for (String tag : fileList) {
Long tagNo = Long.parseLong(tag);
Customer customer = DatabaseInterface.getCustomer(tagNo);
customer.incrementNoOfTimesRecycled();
DatabaseInterface.UpdateCustomer(customer);
}
} catch(IllegalArgumentException ex) {
ex.printStackTrace();
}
}
when the method returns void, you can't test the method output. Instead, you must test what are the expected consequences of that method. For example:
public class Echo {
String x;
public static void main(String[] args){
testVoidMethod();
}
private static void testVoidMethod() {
Echo e = new Echo();
//x == null
e.voidMethod("xyz");
System.out.println("xyz".equals(e.x)); //true expected
}
private void voidMethod(String s) {
x = s;
}
}
It might not be always true, but basic concept of unit test is to check if function works as expected and properly handling errors when unexpected parameters/situation is given.
So basically unit test is against the functions that takes input parameters and return some output so we can write those unit test.
The code like yours, however, includes some other dependency (database call) and that's something you can't execute unless you write integration-test code or real database connection related one and actually that's not recommended for unit test.
So what you need to do might be introducing unit test framework, especially Mockto/Powermock or some other stuff that provides object mocking feature. With those test framework, you can simulate database operation or other function call that is going to be happening outside of your test unit code.
Also, about how do I test void function, there is nothing you can with Assert feature to compare output since it returns nothing as you mentioned.
But still, there is a way for unit test.
Just call updateCustomerTagCount() to make sure function works. Even with just calling the function, those unit test can raise your unit test coverage.
Of course for your case, you need to mock
ImportTagJob.fetchData();
and
DatabaseInterface.getCustomer(tagNo);
and have to.
Let mocked
ImportTagJob.fetchData();
throw empty list as well as non-empty list and check if your code works as you expected. Add exception handling if necessary. In your code, there are two condition depends on whether fieList are null or non-null, you need to test it.
Also, mock those objects and let them throw IllegalArgumentException where you expect it to be thrown, and write an unit test if the function throws a exception. In Junit, it should be like
#Test(expected = IllegalArgumentException.class)
public void updateCustomerTagCountTest(){
// mock the objects
xxxxx.updateCustomerTagCount();
}
That way, you can ensure that function will throw exception properly when it has to.

Confusion - Assertion Appropriate Usage

I am taking this code snippet from K&B practice exams.
public class Later {
public static void main(String[] args) {
boolean earlyExit = new Later().test1(args);
if (earlyExit) assert false; // LINE 5
new Later().test2(args);
}
boolean test1(String[] a) {
if (a.length == 0) return false;
return true;
}
private void test2(String[] a) {
if (a.length == 2) assert false; // LINE 13
}
}
The answer in K&B states that, LINE-5 AND LINE-13 are in-appropriate use of assertions.
I would like to know why. Here is my observation after reading topic of assertion from
K&B.
1.I do understand, LINE 5 is in-appropriate because it is using assertion to validate
command line arguments. Assertions should never be used to validate command line arguments.
2.In answer, it also states that, LINE 13 is also in-appropriate use of assertions. Good practice
in assertions states that, you can use assertions to validate arguments to your private methods. So
my question is why LINE 13 is in-appropriate use of assertions.
Any insights over this will be helpful.
Assertion (assert keyword in java) are used to verify the correctness of an invariant in code, precondition or postcondition. They are used to test your assumption in code to catch inconsistent state and are - usually - an indicator of a bug or a unwanted flow execution.
Assertion are disabled as default because they shouldn't throw in production and asserted code is not executed
public class AssertionTest {
private boolean productionCode(){
System.out.println("Prodution code executed");
return true;
}
private void assertion() {
assert productionCode();
}
}
with assertion enabled output is :
Prodution code executed
and with assertion disabled output is...nothing! so be carefully
Syntax:
assert <boolean expression>; throws an AssertionError if is false
assert <boolean expression> : <expression with value> throws AssertionError with detail message if is false
In your example
private void test2(String[] a) {
if (a.length == 2) assert false; // LINE 13
}
you are using it in a wrong way because the right way is
private void test2(String[] a) {
assert (a.length != 2);
}
means: a MUST have a lenght not equals 2 else is an error
Read here for Oracle documentation.
Assertions are used to check for code invariants. You should never do input validation by using assertions, because usually they are disabled at runtime, that's why LINE 5 is inappropriate.
Q:Assertion advocates that we can use assertion to validate private methods.
A: Yes, you can validate private method's arguments with assertions, because they are not visible to the public - i.e. if assertion fails it means that there is a logic/programmers mistake somewhere in the caller, but I'd recommend using if/else/exceptions constructs. As I said above, you should never validate public methods, because in practice everyone can pass anything to the method and if assertions are disabled bad things will happen :)

Not using an if statement in Java

This is a very odd, and quite specific question.
Ultimately I am trying to write a program convert that takes in java source, and transforms it such that it does not use (Among other things)
Arrays
Loops
User defined methods
If statements
This is a challenge that I set for myself, after my teacher told me that it was impossible to write a program without using these things.
I have most of these worked out, including function inlining and array substitution, however I cannot work out how to manage an if statement.
In C++ I'd use labels and gotos and maybe ?:, however Java does not support GOTO statements.
My question is this:
Given a section of code,
if(CONDITION)
{
//More code in here
}
How can transform it such that it is functionally the same, however does not use the if keyword. Note that loop structures are also out of the question.
Given this, it would be easy to create else and else if statements.
However I am also unsure of how to create loops using this, as there is no GOTO statement and methods are out of the question.
Edit:
Please note that switches are also not allowed, nor is recursion (Ruled out by the fact that you cannot define user methods, and a recursive main function wouldn't work with every program)
The ?: operator does not work for all situations. AFAIK you cannot call a void function with ?: as it wants to assign a value as part of its operation.
These conditions come from the IB Computer Science SL requires course, I am taking HL and as a class we were laughing at the 'mastery' factors for SL which include 'if' statements (And if fact 3/15 of them are 'User defined methods with params and return types) The challenge is effectively to FAIL a mastery test in SL while still producing a program that functions correctly.
Answer: (By bdares)
String result = (CONDITION)?"0":"A";
try{
Integer.parseInt(result);
//Condition is true
} catch(NumberFormatException e){
//Condition is false
}
if(A) {
X();
}
else{
Y();
}
can be converted to:
A?X():Y();
You can nest these all you want, or simply remove one side of the : and get a simple if. The conditionals are easy.
If you want it to work for void methods, here's a way:
String result = A?"0":"A";
try{
Integer.parseInt(result);
X();
} catch(NumberFormatException e){
Y();
}
I'm not sure it's possible to write an entire useful program without using an if statement. However, I think what your teacher may be getting at is that you can write code to follow the same "logical" path by using a more object-oriented approach in place of an if statement. For example:
public interface Moveable {
void move(int x, int y);
}
public class Ball implements Moveable {
private int x;
private int y;
public void move(int x, int y) {
this.x = x;
this.y = y;
}
}
public class NullMoveable {
public void move(int x, int y) {
// Do nothing.
}
}
... and then in your main application code:
Moveable mv = new NullMoveable();
// Move object; don't care if it's a Ball or a NullMoveable
// so no need to explicitly check with an if-statement.
mv.move(10, 50);
The principle here is that the fewer possible paths there are in your code (due to if statements) the easier it is to test and maintain.
You can use the conditional operator and a switch:
switch( CONDITION ? 1 : 0 )
{
case 1:
//... true code
break;
case 0:
//... false code
break;
}
For the loops you can unroll your code to some predefined maximum and use labeled breaks to jump out of the unrolled code early based on some condition. You can use break to end any code block in Java not just loops.
The Java language has no goto but the Virtual Machine has it, so you could of course also generate JVM instructions directly although this would be not much different from a regular Java compiler which also translates all ifs an loops into jump instructions.
In some cases, you can use bit manipulation. For example:
if(x > 0) // positive number
{
isPositive = true;
}
else // negative number
{
isPositive = flase;
}
is equivalent to:
isPositive = (x >> 31) == 0;
EDIT:
This is just an example, of course you can do much more complex bit manipulation with one statement instead of doing it using bunch of if statements.
If you were allowed to use anonymous inner classes (these probably classify as user-defined methods, but I'll let you be the judge):
if(COND) {
X();
} else {
Y();
}
becomes:
ifReplacement(COND,
new Runnable() { public void run() { X();}},
new Runnable() { public void run() { Y();}});
with signature:
public static void ifReplacement(boolean condition,
Runnable ifBranch,
Runnable elseBranch)
Of course, JDK8 lambdas would make this much nicer:
ifReplacement(COND, ()->X(), ()->Y());

Categories

Resources