I'm currently a Teacher's Assistant for a class that uses Java. I'm trying to write a snippet of code that will test to make sure that student's methods are correct, but often times the student won't even implement the method, or they'll call it something incorrect, which obviously will cause a Unresolved Compilation problem when my test code is run. Is there a way to catch this error during runtime, so that my test code can execute without having to play around with the code submitted by the student?
edit: Just discovered that an Unresolved compilation problem is generated by the compiler before runtime. With this in mind, is there a way to do what I explained above?
edit: Also, I don't have any control over the way that assignments are structured, so I can't introduce interfaces, or stubs, etc.
If I were a TA, I would write some unit tests and tell the students to make the test pass. Get them into testing early on.
If the code doesn't compile, it doesn't make sense to detect that at runtime. You can't run if it won't compile.
If you use reflection you can check if the method exists, invoke methods, and iterate though existing methods to possibly find the student's method.
See the UrlClassLoader class for loading the students code from file.
If I understand your question, you're trying to validate both the interface that the student implements as well as the correctness of the implementation. The reflection API would allow to determine if a Class has implemented the correct API and if it has, invoke that API. Look at java.lang.Class, java.lang.Method, etc.
Sounds like you have entered into the object orient portion of your course now. I think it might be a good idea to create a super class that has all of the assigned methods stubbed out. Then students can simply extend that super class and implement the methods. Your stubbed ones should just throw a RuntimeException which would cause the corresponding unit tests to fail. That should allow you to create unit tests with having to worry too much about students not implementing particular methods.
Related
I'm looking to add some junit to our code base.
We have a set of classes that inherited from an abstract base class. The inheritance is several layers deep (Base-> A, B, C ->C1, C2, C3->C3-1, etc). Sometimes someone overrides a method of a class (Class A) which has several child classes. But because of that, we get bad results for those in call children classes of Class A.
So, I'm looking for solutions to be able to try to prevent this and create a testing framework to deal with this.
My initial though is that we would need to create a TestSuite that would need to check that the TestClass has at least 1 test case for every method in the Base class via reflections. This would make sure the person who added a overridden a method in a mid-level Class know that their change will affect child classes.
Also, I was talking to someone who said that there might be library already out there that does this.
I'm looking for thoughts and examples of how to write tests to handle this scenario. Refactoring is not an option in this case.
Sorry, but the proper answer to a bad design is not to "fix" it by coming up with "interesting" unit tests.
You fix a bad design by fixing the bad design.
In other words: the very first thing about OO to understand is LSP (Liskov substitution principle). In other words: when your developers change something in "the middle" of your inheritance tree, and that causes unexpected behavior in child classes further down, then you should rather invest in education and design sessions.
Beyond that, you don't need specific testing. When all public methods of your public classes are thoroughly tested, then you should quickly catch such kind of problems. But there is no way to determine pro grammatically that you have good tests for all classes. The fact that there are n test methods for some method X ... doesn't tell anything about the quality of any of the test methods. It doesn't help to know that you have "enough" tests ... but sorry, unfortunately, half of the tests isn't doing proper checking/verification; and thus they just keep passing all the time.
Long story short: you are looking at an XY problem here. Your Y problem is "our tests don't fail when we mess up code". But your X problem is: you created a bad design in the first place; and now you are searching for ways to work around that. And that will simply not work out in the long run.
Is there a way to use a service method (a method that is implemented in the service layer (Interface) ) only in test classes?
in my service interface i have a method that i want to use it only in test class
and prevent or show some warning to other developers that doesn't use it in their
managerImpl or other palace such as controller
Lets be precise about wording:
If you are really talking about a method of an Java interface; then Java8 would allow you to provide a default implementation that could throw an exception for example; and then you have very specific classes that implement this interface and maybe override that one method for test purposes.
If you are talking about "interfaces" in general; such as "the list of methods of some class" ... then this kind of "base throws" and "children override" could work as well.
Of course, the first answer might be visibility itself. If we are not talking about a real interface; you could at least make the method package protected; then usage is restricted to the same package.
Another option would be to follow ISP and segregate your interfaces. If there is something that should only be used for "testing"; then consider putting those things into some "TestSupportInterface"; or something alike.
But again; most of these ideas work "by convention"; by providing some sort of information that the user has to digest ... but that can't be enforced.
Finally: you could consider to change your production code. Very often you might not need such "special test getters". In other words: if your tests are working like "fetch state of X. do something with X. fetch state of X again and compare". Sometimes this can be changed to behavior based testing (you don't check what happens to X; but you check what X does to Y, Z, ...).
No, there's no concept in Java to warn developers about using methods.
Rethink if you 'really' need such a method, or if you could change your design to not require such a back door. (e.g. utilize the power of dependency injection). From my experience this is always possible.
If you are still convinced that you want this method implement it in your test code (e.g. by subclassing), not in production code.
It's generally better not to put anything in your production code "only for tests".
You could create a service dedicated to all users suppression and place it in your test classpath.
Depending on your implementation, this service might be a subclass of your production user service.
In addition to the other good answers: If you really need a method to be called by a test case but not by production code, you can make this method private. So unless someone changes the visibility nobody will use this method. And in your test case you can call it via PrivateAccessor.
But be careful: This is mostly considered as code smell. For your IDE this is a private and unused method, so there will be a warning message. And someone else could remove this method because of this.
I was studying about the Dagger 2 - dependency injection library for Android - and in many articles, when the autor compares the Dagger 2 with it's older version ( Dagger ), He says this:
(...)
The new release, as promised, addresses many of the problems of the original:
No more reflection — everything is done as concrete calls (ProGuard works with no configuration at all)
(...)
From: https://blog.gouline.net/dagger-2-even-sharper-less-square-b52101863542#.w33tjdttt
I know that Reflection can be used for observing and modifying program execution at runtime, but what about these Concrete Calls? What are them and how they are different from Reflection?
Obs.: Would be great if anyone could provide some sample code/ use case about how to create/ use these Concrete Calls.
Well...Dagger used some reflection and dagger 2...doesn't.
Dagger 2 uses annotation processing to generate code at compile time. All those annotations you put on your classes, #Component, #Module, and so on, signal to the dagger 2 compiler what to do.
It will use them to create a dependency graph, validate it, and then create the code. There are some benefits to this approach, compared to dagger:
Compile time validation (if you have dependency cycles, or can't provide something, it won't compile and you get an error at compile time, and not an exception when running your program)
Performance (everyting is just simple java—no reflection involved)
Proguard 'support' (by not relying on reflection, there will be no issues with proguard)
So, as already mentioned in the comments, concrete calls in this context would mean the elimination of reflection and generating code. Dagger 2 will produce a whole lot of source files, with which you can also easily debug your code.
Concrete calls are where you call the method directly, and the compiler creates a call instruction:
System.currentTimeMillis();
This is is the fastest way to call a method, but it only works if you know at compile-time which method you need to call (which is 99% of the time the case). This is how you write code normally.
Sometimes, you don't know what method you need to call. Maybe a user or a file tells you which method you need to call. For this, you need to use reflection. This is much slower, but allows you to dynamically indicate which method to call:
Scanner in = new Scanner(System.in);
String method = in.next();
// Reflection invocation:
Object result = System.class.getMethod(method).invoke();
System.out.println("Result was: " + result);
This would allow you to type currentTimeMillis into the command line, and return the value. You could also type nanoTime and it would print the result of that too.
Because reflection is an extra layer of indirection (there is no System.currentTimeMillis() call in the reflection code above - but it could call it!), tools which operate by scanning through the compiled code and rewriting method calls will fail to properly handle reflection calls.
I am working on a program that will be a sort of game for beginner programmers. I intend to provide a field where the users can write code as required (method, class... ). When the user wants to submit the code, I will copy the content of the text field into a .java file, call the compiler to compile this class, and then I want to test whether the code works okay using jUnit.
Well, I know that jUnit is used for development purposes, but I think it could be very useful implementing it in this case as well.
Now the problem is that when I will need to compile my program, the class which will supposedly be tested (the user's code) is not going to be there. So I cannot just call
assertEquals( "Wrong sum", 6, Foo.sum( 4, 2));
because it will not know what Foo class is, since it will never be there at the time of compilatoin - before the user runs the application and starts coding.
I thought I could create a dummy class, just for the sake of compilation, but then when I will need the real thing, I won't be able to replace the file or write another file like Foo2.java, because the FooTest.java will only operate with object Foo....
I would really appreciate your suggestions guys!!! What can I do to deal with this situation?
Thanks :)
Two options:
Have the user implement an interface and use the interface in the JUnit
Use reflection to get the public method from the class and call it.
Reflection Version:
If you have an instance of the class you want to test (could be of type Object), use getClass to get the Class object. Then use getDeclaredMethods to get a list of the Methods. Iterate the Methods till you find the one you want to test (hopefully the only public method).
I have completed my project, but cannot get the testing class to work. I know this is because i wrote the code in probably the worst possible way. However, it's too late to change now, and honestly i don't want too either. Could someone suggest a possible way of a testing class based on the code i currently have...
Your code is untestable. You need to use more object oriented way of programming. Try to refactor code into few shorter methods. Then you can test separate methods.
For unit testing I recommend Junit
Your code might work because you extend Pizza and then in your main you just set the static attributes. But there is absolutely nothing you could test here, as you have 0 methods and 0 objects.
You can't even instantiate your Pizza class, as all its attributes are static and an instance would therefore be useless.
All you can test is assigning values to static attributes, but I guess we can expect that to be bugfree ;-)