I would like to write JUnit test for my Eclipse RCP while I continue developing the code. When starting the application the different plugins initialize variables of various plugins/classes (mostly within their start methods) which are needed for the correct functionality.
If this initialization doesn't happen, it is impossible to test code because it depends on those values.
How do I solve this issue without creating a lot of dummy values?
What is the general approach to testing Eclipse RCPs?
You're facing a common problem: Too many dependencies. You need to cut them.
With Eclipse 3, this is going to be somewhat hard. Try to split the code into things that depend on the Eclipse platform running and everything else. Eclipse often uses interfaces, so you can test many things using mocks.
With e4, things got more simple since many services will be injected, making mocking and testing even easier.
But the goal must always be to have as much code as possible that doesn't depend on SWT or the platform. Create your own interfaces if you have to. The runtime imlementations just wrap Eclipse code. For tests, you can use mocks to simulate the Eclipse runtime.
You can run tests using JUnit plugintest, that will start up the plugin framework and will allow for testing of plugins. But this usually only solves some of the issues. The best suggestion is as Aaron suggests to separate functionality as much as possible to the point where all your actual code are just plain old java objects that you can test normally. All dependencies to Eclipse are in different classes and are kept as thin as possible so that they dont require testing.
This can be difficult to achieve, so mocking may be required. Another trick I've resorted to at times is to use Java reflection to change values of private fields, see this question
Related
I was reading about code-injection at run-time and there are many tools/APIs available like Javassist, GluonJ and AspectJ which provide features to inject code. However, I did not understand purpose for injecting code at run-time while we can do override behaviors by sub-classing in Java. With Javassist and GluonJ, I can create classes at run-time but why does anyone do that, in the first place? Can anyone please help me to understand the difference and purpose of code injection ?
Code injection is usually used into application that are used to modify/check/trace other software. In Java we usually reffer to this kind of library as Bytecode modification libraries so if you look on the internet you will probably find more information under this name.
Here I listed a couple of examples of big and famous projects that I now are using Bytecode modification into their cores:
Evosuite: this project takes an application in input and generates unit test for it. Code injection is used to explore the desired project and dependencies and traceability
JaCoCO: this project is a tool for Java project. It is supposed to be attached to your application and once you run your JUnit tests it is going to generate a report on the coverage achieved. Obviously here code injection is necessary to trace every method call made during test execution.
I have an exported Eclipse Java Project in my server and I want to be able to compile the project and use ASTParser with JDT.
I'm able to compile the project using BatchCompiler, however it runs on console and gives me PrintWriters instead of an array of problems and errors. Also I want to be able to use proposals in Eclipse and BatchCompiler didn't built for this purpose.
Therefore I tried to use ASTParser, it can be used with either char[] or ICompilationUnit. CompletionProposalCollector and org.eclipse.jdt.internal.compiler.Compiler.Compiler needs ICompilationUnit so I have to create an ICompilationUnit which only can be created by an IJavaProject (https://dl.dropboxusercontent.com/u/10773282/2012/eclipse_workspace.pdf) in order to be able to use these features.
It seems the only way to create IJavaProject is to use ResourcesPlugin.getWorkspace(), however it returns java.lang.IllegalStateException: Workspace is closed. on my computer and it seems the reason is that the program that I coded is not an Eclipse plug-in.
Is there any way to create IJavaProject without Eclipse environment?
From the comments, it looks like you are trying to do more than just parsing, you actually want to get some form of content assist.
I'm afraid that you're asking for too much. There is no simple way to get the power and flexibility of JDT outside of a running Eclipse instance (believe me, I've tried). There's no simple way, but if you are brave and strong willed, you can one of try following:
Run a headless Eclipse on your server that works on top of an actual workspace. This would be the easiest to implement, but would be the most resource intensive and least flexible way of doing things.
Use the jdt core jar, and create alternate implementations of the IResource hierarchy, and the parts of JFace that are used by the the parser and the CompletionEngine. This would likely be the most feature-rich way to go, but also the most brittle. I can't guarantee that this would work as you may need to create some very complex stubs for internal Eclipse non-API classes.
Avoid the CompletionEngine and the ASTParser entirely and just use the batch compiler. You would then need to provide an alternate implementation of org.eclipse.jdt.internal.compiler.env.INameEnvironment. This implementation would be able to find types, files, and compilation units in your actual project structure. You'd need to reimplement support for content assist, but this would most likely work reasonably well.
I am actually fairly interested in doing something like this (but I lack the time to do it). If you are seriously considering creating a headless JDT that can run on a server, feel free to ask for more information. I am quite familiar with JDT internals.
I've had a similar problem. Here is how to use ASTParser without Eclipse (it just needs the core JDT JAR on the classpath): http://blog.pdark.de/2010/11/05/using-eclipse-to-parse-java-code/
I'm working on a plugin which editor augments on the existing JDT (Java) editor
using aspects.
Now, Eclipse text editors that derive from AbstractTextEditor are
organized in clear components, following an MVC architecture. Those
components are then accessed through precise paths,
e.g. reconciliation. You can find one example of a custom reconciler and
the assumptions it can (and does) use on the behavior of the editor
here.
I'd like to write headless unit tests against those assumptions, that
would check that my weaving through aspects has not broken anything along
the way. For example, in the case of reconciliation, I would like to
open an editor, input some incorrect content (with respect to some
reconciliation strategy), wait for a while, and check that Problems are
indeed reported.
Note that which problems are reported, or how they would be signaled to
the user in a UI component doesn't concern me : I want
to test that my swapping a SourceViewer for a custom one through aspects
doesn't break editor logic, not my specific reconciliation strategy.
(In fact, I'd
probably mock it for that test. Moreover, the UI testing, being
presumably not runnable in a headless fashion, is beyond the scope of my
question.)
It seems this should be easy to do if the appropriate structures
existed. Do they ? Is there any test framework or mocks in sync with Eclipse's
architectural assumptions that would let me do what I have in mindĀ ? Those would have to reproduce workflow behavior of the existing Eclipse editor. Surely this would be among Eclipse's own unit tests, right ? ... though
I can't seem to find anything of the sort. Any ideasĀ ?
I have asked that same question on the eclipse core platform mailing-list, and got a great answer from Dani Megert giving me pointers to Eclipse's own test framework. The Junit plugin tests are released for download as part of the extended SDK, and browsing the git source lets you see there are already tests against the model or interacting with some of the Editor components.
Ie. I have a GUI package, and a Logic package.
How can I prevent the Logic classes from importing GUI classes? Others(or myself) working on the same project might do that, which I want to prevent.
A solution could for example be a check in JUnit, that fails if its done, or a runtime check that throws an exception. Something along these lines, but how to do it?
You can write such a test using JDepend or DependencyFinder or Degraph.
Degraph is the only of the three tools that explicitly is intended to actually write tests for cases like this. Also AFAIK JDepend does not find all dependencies in more recent Java Versions (like classes mentioned in Annotations).
I'm the author of Degraph so I'm obivously biased.
I created the JabSaw project. It allows you to define modules by using annotated classes and to express the relationships between the modules. By default, a module contains all classes in a single package.The restrictions can be checked using a Maven plugin, from the command line or from a unit test. This should solve your problem.
One solution which comes to my mind is make GUI classes package private. Although you cannot isolate only one package and say, only Logic classes cannot use GUI, but other can.
Can go run dynamically in order to be used for a plugin based application ?
In eclipse, we can create some plugins that Eclipse can run dynamically.
Would the same thing be possible in Go ?
I'll argue that those are two separate problems :
having dynamic load
having plugins
The first one is simply no : A Go program is statically linked, which means you can't add code to a running program. And which also means you must compile the program to let it integrate plugins.
Fortunately, you can define a program accepting plugins in Go as in most languages, and Go, with interfaces and fast compilation doesn't make that task hard.
Here are two possible approaches :
Solution 1 : Plugin integrated in the main program
Similarly to Eclipse plugins, we can integrate the "plugins" in the main program memory, by simply recompiling the program. In this sense we can for example say that database drivers are plugins.
This may not feel as simple as in Java, as you must have a recompilation and you must in some point of your code import the "plugin" (see how it's done for database drivers) but, given the standardization of Go regarding directories and imports, it seems easy to handle that with a simple makefile importing the plugin and recompiling the application.
Given the ease and speed of compilation in Go, and the standardization of package structure, this seems to me to be a very viable solution.
Solution 2 : Separate process
It's especially easy in Go to communicate and to handle asynchronous calls. Which means you could define a solution based on many process communicating by named pipes (or any networking solution). Note that there is a rpc package in Go. This would probably be efficient enough for most programs and the main program would be able to start and stop the plugin processes. This could very well feel similar to what you have in Eclipse with the added benefits of memory space protection.
A last note from somebody who wrote several Eclipse plugins : you don't want that mess; keep it simple.
Go 1.8 supports plugins (to be released soon Feb 2017.)
https://tip.golang.org/pkg/plugin/
As dystroy already said, it's not possible to load packages at runtime.
In the future (or today with limitations) it may be possible to have this feature with projects like go-eval, which is "the beginning of an interpreter for Go".
A few packages I found to do this:
https://golang.org/pkg/net/rpc/
https://github.com/hashicorp/go-plugin
https://github.com/natefinch/pie