Wednesday, August 18, 2010

Run customized process to notify JUnit results

I made a plugin to run customized process to notify JUnit results. Before I introduced to notify JUnit results to Grows Eclipse Plugin beforeThen Ketan's comment, "+1 for a custom command line preference this would be useful to people on other operating system". I agreed with him.So I made a plugin.If you'd like to install the plugin, could you please download jar file and copy to your dropins folder in your Eclipse.Default setting is to run growlnotify.If you want to customize that process, please open preference page and choose "Java->JUnit->Process Notification" like below.

If I use this plugin on Ubuntu linux 10.4, this plugin integrated with NotifyOSD.
The process setting is like below.

/usr/bin/notify-send -i /home/kompiro/>eclipse/icon.xpm ${summary} ${detail}

If I use this plugin on Windows, this plugin integrated with Snarl and Snarl_CMD.
The process setting is like below.
C:\Snarl_CMD_1.0\Snarl_CMD.exe snShowMessage 2 "${summary}" "${detail}

I think this plugin is not only use for notification. If you'd like to store testing log, you can use shell, script, batch, and so on.
Enjoy your testing!

Sunday, July 18, 2010

WizardDialogTestRunner for SWTBot

I think SWTBot is a great framework for test on SWT Application like Eclipse.
So I always use this framework for my plugins development.
But there are no WizardDialog Helper class.
So I implemented it below.
package org.eclipse.swtbot.jface;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
import org.eclipse.swtbot.swt.finder.results.VoidResult;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.TestClass;
public class WizardDialogTestRunner extends SWTBotJunit4ClassRunner {
private IWizard newWizard = null;
public WizardDialogTestRunner(Class<?> klass) throws Exception {
super(klass);
}
@Override
protected void runChild(final FrameworkMethod method, final RunNotifier notifier) {
Shell parentShell = new Shell();
try {
newWizard = newWizard();
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
final boolean[] finishPressed = new boolean[1];
final WizardDialog dialog = new WizardDialog(parentShell, newWizard) {
@Override
protected void finishPressed() {
super.finishPressed();
finishPressed[0] = true;
}
};
final Exception[] ex = new Exception[1];
final boolean[] done = new boolean[1];
Runnable r = new Runnable() {
public void run() {
try {
WizardDialogTestRunner.super.runChild(method, notifier);
} catch (Exception e) {
ex[0] = e;
} finally {
if (dialog.getShell() != null && dialog.getShell().isDisposed() == false) {
UIThreadRunnable.syncExec(new VoidResult() {
public void run() {
dialog.close();
}
});
}
done[0] = true;
}
}
};
Thread nonUIThread = new Thread(r);
nonUIThread.setName("Runnning Test Thread");//$NON-NLS-1$
nonUIThread.start();
dialog.open();
waitForNonUIThreadFinished(parentShell, nonUIThread);
if (ex[0] != null) {
throw new IllegalStateException(ex[0]);
}
}
private void waitForNonUIThreadFinished(Shell parentShell, Thread nonUIThread) {
Display display = parentShell.getDisplay();
while (nonUIThread.isAlive()) {
try {
if (!display.readAndDispatch()) {
display.sleep();
}
} catch (Throwable e) {
}
}
}
@Override
protected Object createTest() throws Exception {
Object test = super.createTest();
if (newWizard != null) {
try {
Field field = test.getClass().getField("wizard");
field.set(test, newWizard);
} catch (NoSuchFieldException e) {
}
}
return test;
}
private IWizard newWizard() throws InstantiationException, IllegalAccessException {
TestClass testClass = getTestClass();
Annotation[] annotations = testClass.getAnnotations();
IWizard newWizard = null;
for (Annotation annotation : annotations) {
if (annotation instanceof WithWizard) {
WithWizard wizardAnnotation = (WithWizard) annotation;
Class<? extends IWizard> value = wizardAnnotation.value();
newWizard = value.newInstance();
}
}
return newWizard;
}
}

package org.eclipse.swtbot.jface;
import java.lang.annotation.*;
import org.eclipse.jface.wizard.IWizard;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface WithWizard {
Class<? extends IWizard> value();
}
view raw WithWizard.java hosted with ❤ by GitHub


And this is a sample code how to implemente bu using these class.
package org.kompiro.jamcircle.kanban.ui.wizard;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.io.File;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swtbot.jface.WithWizard;
import org.eclipse.swtbot.jface.WizardDialogTestRunner;
import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.waits.Conditions;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotText;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kompiro.jamcircle.kanban.ui.Messages;
@RunWith(WizardDialogTestRunner.class)
@WithWizard(CSVExportWizard.class)
public class CSVExportWizardTest {
private SWTBot bot;
private SWTBotShell target;
public CSVExportWizard wizard;
private IRunnableWithProgress runner;
@Before
public void before() {
bot = new SWTBot();
target = bot.shell(Messages.CSVExportWizard_title);
runner = mock(IExportRunnableWithProgress.class);
wizard.setRunner(runner);
target.activate();
}
@Test
public void show() throws Throwable {
assertThat(wizard, is(notNullValue()));
bot.button(IDialogConstants.CANCEL_LABEL).click();
assertThat(Conditions.shellCloses(target).test(), is(true));
}
@Test
public void not_close_wizard_when_click_finish_and_file_is_empty() throws Throwable {
assertThat(bot.button(IDialogConstants.FINISH_LABEL).isEnabled(), is(false));
}
@Test
public void finish_is_enabled_when_file_form_is_exists_path() throws Exception {
SWTBotText fileText = bot.textWithLabel(Messages.CSVExportWizard_output_label);
assertThat(fileText.getText(), is(""));
File tmpFile = File.createTempFile("tmp", ".txt");
String path = tmpFile.getAbsolutePath();
fileText.setText(path);
assertThat(bot.button(IDialogConstants.FINISH_LABEL).isEnabled(), is(true));
}
@Test
public void runner_is_called_when_finish_is_pushed() throws Exception {
SWTBotText fileText = bot.textWithLabel(Messages.CSVExportWizard_output_label);
assertThat(fileText.getText(), is(""));
File tmpFile = File.createTempFile("tmp", ".txt");
String path = tmpFile.getAbsolutePath();
fileText.setText(path);
bot.button(IDialogConstants.FINISH_LABEL).click();
verify(runner, times(1)).run((IProgressMonitor) any());
}
public static void main(String[] args) {
final Shell parentShell = new Shell();
IWizard newWizard = new CSVExportWizard();
WizardDialog dialog = new WizardDialog(parentShell, newWizard);
dialog.open();
}
}

How do you think about it?

Saturday, June 26, 2010

Eclipse-tan for Helios

I'm waiting for a long time to release Eclipse Helios!

My friend, @torazuka made a new splash screen for Eclipse Helios.


If you'd like to use the screen shot,
1. download the image
2. open eclipse.ini
3. fix -showsplash path to the bmp file.(You can use relative path like below.)

-showsplash
../Resources/splash_eclipse-tan_helios.bmp


The image is published below.
http://dl.dropbox.com/u/3779351/MDD/splash_eclipse-tan_helios.bmp

Thursday, May 27, 2010

Notify JUnit Results to Growl Eclipse Plugin

I made a Eclipse Plugin for long-period testing on Eclipse for Mac.


Yes!, This plugin notify the test result to Growl.This is simple, but effective to drive to develop your application!
This plugin uses native library. So there are some constraint to use it.
If you use Eclipse for cocoa 64 bit edition, you can't use this plugin because the native library can't load on your Eclipse Environment.

The plugin is published below.
http://kompiro.org/download/junit.extensions.eclipse.quick.mac.growl_0.1.0.201005252224.jar
If you interested in this plug-in, then download and put it dropins folder!

Thursday, April 8, 2010

Where is DS Annotation?

I used Declarative Service in my application, JAM Circle.
Declarative Service is cool stuff.
It makes to solve bundles startup order.
But I confused a thing.
How do I inject the service at startup time?
I think services needs to initialize at startup.
So I choosed the way to solve by singleton class like below.

scr.xml
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.kompiro.jamcircle.kanban.ui.KanbanUIContext">
<implementation class="org.kompiro.jamcircle.kanban.ui.KanbanUIContext"/>
<reference bind="setKanbanService" cardinality="1..1" interface="org.kompiro.jamcircle.kanban.service.KanbanService" name="KanbanService" policy="static"/>
<reference bind="setScriptingService" cardinality="1..1" interface="org.kompiro.jamcircle.scripting.ScriptingService" name="ScriptingService" policy="static"/>
</scr:component>

and implementation of Context class(The name inspired from "ApplicationContext")

package org.kompiro.jamcircle.kanban.ui;

import org.kompiro.jamcircle.kanban.service.KanbanService;
import org.kompiro.jamcircle.scripting.ScriptingService;

public class KanbanUIContext {

private static KanbanUIContext context;
private KanbanService kanbanService;
private ScriptingService scriptingService;

public KanbanUIContext() {
KanbanUIContext.context = this;
}

public static KanbanUIContext getDefault(){
return context;
}

public KanbanService getKanbanService() {
return kanbanService;
}

public void setKanbanService(KanbanService kanbanService) {
this.kanbanService = kanbanService;
}

public ScriptingService getScriptingService() {
return scriptingService;
}

public void setScriptingService(ScriptingService scriptService) {
this.scriptingService = scriptService;
}

}


It's not good way(T_T)... KanbanUIContext is a singleton class and be used to call ServiceLocator Pattern. It is not easy to test by code...
I haven't know there is no way to inject to use annotation for field injection.
Is there any way to use annotation and field injection?

Wednesday, April 7, 2010

JAM Circle 0.8.0 released

Hi all!

I'm glad to announce to release my RCP application JAM Circle 0.8.0!
Download site
https://sourceforge.net/projects/jamcircle/files/

Project Page
http://kompiro.org/jamcircle

These are New Feature.
* Migrated p2 base Eclipse platform
* Added some Board customize extension point
* JRuby Scripting Console
* improved figures design
* added Japanese resource
* added Eclipes Plug-in Edition
* fixed some bugs