Tuesday, August 18, 2009

Using FlexUnit 4 with Flex 3: Sample Application

Introduction
We had hard time finding on the internet a sample like this. So, here's ours. Additional steps required for this test to be run:
  • download FlexUnit 4 from their site.
  • add the FlexUnit swc files to the project's classpath
  • copy the sources below into your project and adapt them (use the view source icon in each source code frame below to view/copy the source code).
  • once everything is on place, right click on the TestRunner and select Run Flex Application.
At the end of the article, we have added some notes about using FlexUnit with FlashBuilder 4 and Flex 4
Enjoy! It's a great tool!

File structure

Tested Object

package olcc.account
{
public class Account
{
public function Account(){
}

private var balance:Number=0;

public function deposit(amount:Number): void {
balance=balance+amount;
}

public function withdraw(amount:Number): void {
balance=balance-amount;
}

public function getBalance():Number {
return balance;
}
}
}
Test Suite (Optional)

package olcc.account
{
import org.flexunit.runners.Suite;

[Suite]
[RunWith("org.flexunit.runners.Suite")]
public class MyTestSuite
{
public var t1: AccountTest;

}
}


Unit Test

package olcc.account
{
import org.flexunit.Assert;

public class AccountTest
{
[Test]
public function testNew():void {
var account:Account = new Account();
Assert.assertEquals("Expecting zero account balance", 0, account.getBalance());
}

[Test]
public function testDeposit():void {
var account:Account=new Account();
account.deposit(50);
Assert.assertEquals("Balance on a new account after 50 deposit is 50",50,account.getBalance());
account.deposit(25);
Assert.assertEquals("Balance after 50 deposit and another 25 deposit is 75", 75,account.getBalance());

}

[Test]
public function testWithdraw():void {
var account:Account = new Account();
account.deposit(100);
account.withdraw(50);
Assert.assertEquals("Balance should be: + $100 - $50 = $50",50,account.getBalance());
}
}
}


Test Runner
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns="*"
xmlns:flexunit="http://www.adobe.com/2009/flexUnitUIRunner"
creationComplete="onCreationComplete()">

<mx:Script>
<![CDATA[
import org.flexunit.runner.FlexUnitCore;
import org.flexunit.flexui.TestRunnerBase;
//Add an import statement(s) for the class(es) under test
import olcc.account.MyTestSuite;

private var core: FlexUnitCore;

private function onCreationComplete():void
{
core = new FlexUnitCore();
core.addListener(testRunner);
core.run(MyTestSuite);
}
]]>
</mx:Script>

<flexunit:TestRunnerBase id="testRunner" width="100%" height="100%" />
</mx:Application>

Using FlexUnit 4 with Flex 4

Flex 4 beta2 has support for FlexUnit, and the most recent version of it which is version 4.0. If you go to the New->TestCase menu, FlashBuilder can create for you a whole test class. And add to the flex build path the necessary libraries. This is done pretty well. But when I tried to apply the simple test application presented above to a Flex 4 application, I ran into multiple problems. One critical, as of today, was the issue that the AsDoc for Flex 4 is not available, nor much of the documentation for it. So, some classes from FlexUnit 4 that I needed (like TestRunnerBase), I wasn't able to find. Until these issues are resolved in Flex 4, I decided to use the FlexUnit 4 directly. To do this, I removed the Flex 4 libraries from the build path and added the FlexUnit 4 beta 2 libraries (.swc files). In general, the flex parser is not always stable, which showed up in this exercise and I had a compilation error that shows every other time I compile my TestRunner.mxml (with the same source code), but I can run the tests. Simply, I made sure that the last compilation is a clean one. Also, closing and reopening the project eliminated this issue.

Tuesday, August 11, 2009

FlexUnit Plugin for Eclipse

Since we intend to do unit testing in our Flex+Java development, I have been playing with FlexUnit and have found an eclipse plugin that makes it easier to use (also, in plugin central). Here's a summary and lessons learned on how to start with the plugin

Installation
Follow the installation instructions from here. Once installed, open the plugin's help in Eclipse and configure it. A few points:
  • Download FlexUnit and FlexUnit extension for the plugin.
  • You will need to have Flex Builder 3.
  • You will need a debugger version of Flash Player (I used version 10). A standalone player used by the plugin comes with Flex Builder (directory: player)
  • Follows instructions from Adobe on how to enable logging and error output for Flash Player. When you follow them, after you create a mm.cfg file, you will need to restart all instances of Flash Player for the Logs folder to show up.
Using The Plugin
To use a plugin:
  • Create a unit test using Flex Builder's wizard. I recommend keeping them in another source folder, so they can be easily skipped when releasing the app. For example, keep the flex source in flex-src and flex tests in flex-test. The server code put in java-src and java-test, or whatever language you use for the middle-tier.
  • Create a harness. Right click in the test file in the project navigator, find FlexUnit menu and select Create Harness. This will create a small mxml file for your test. However, if you use FlexUnit 0.9, the code needs a correction. Replace:
    EclipsePluginTestRunner.runTests( new Array(AccountTest.suite()) );
    with
    EclipsePluginTestRunner.run( AccountTest.suite() );
  • Run the test. Right click on the harness file and select Run from the FlexUnit menu. Observer the test results on the nice eclipse viewer.
I had the problem that the test launch process never finishes in eclipse. But it doesn't seem to be harmful. Just ignore it.

Summary
It's a great plugin. It could do quite a bit more, but it's a great start. It worked for me with a FlexUnit 4, when I used the syntax of FlexUnit 0.9. When I switched to FlexUnit 4 syntax, I didn't have to apply the correction mentioned above to the auto-generated harness to compile. However, I didn't get my tests executed. So, I guess, for now, using the FlexUnit 0.9 is a better option. However, I have heard from the plugin author that he intends to do another release of the plugin.

Sunday, July 12, 2009

Graphics - Format Selection

The Problem
So, you decided to edit an picture from you camera. Most likely, it came from the camera as a JPG or JPEG file. However, if you edit it and save, and especially repeat this process couple times, your image will look different. Wherever there was a smooth transition from one color, or shade, to another color or shade, you will notice strange lines, like contour lines on a map.

The Mystery Revealed
The reason is, each time your editing software saves a file in JPEG format, it compresses the image and introduces small changes to your picture. These changes are small and they are not noticeable. Because JPEG compression algorithm is allowed to perform these small changes, it is able to compress the file so nicely. So, it all works great, unless you save it not once but 3, 4 or 8 times. Then these small changes accumulate and the deformations are very well visible and not really pretty. Your picture is ruined.

The Solution
So, what, shall you avoid the JPEG format? Not at all. However, if you decide to edit the picture, save it in a lossless format. You can open it, edit and save as many times as you want, and you picture will not deteriorate. Than, when you are ready to post the picture to your website or print it, save it as a JPEG file. But what is a lossless format? Well, there are two good candidates: TIFF and PNG. TIFF is better, in a way, because it can save more than just the image. It can also save paths and layers (I'm not sure of layers, though). Just make sure, that you don't let the TIFF formatter use JPEG as compression. You would get into the same problem as described above. PNG may be even a bit smaller, but it will not save anything more than the image itself.

Tool
GIMP image editor will allow you to open and save in all these formats without problems.

Sunday, July 5, 2009

Date, Time, SQLite and Android

This post summarizes my recent experience (problem, finally solved) with storing and then reading and displaying the date and time in Android application.

Storing the current time/date in SQLite
The most common way is to do:
database.execSQL("update TABLE_NAME set COLUMN_NAME = datetime('now') where ...");
As a result, SQLite stores a string representing the current time in UTC (GMT), using the ISO8601 date/time format. This format (YYYY-MM-DD HH:MM:SS), is by the way suitable for date/time comparisons. The fact that the value stored is in UTC and not in a local time zone, is actually nice. More about it below.

Retrieving a time/date and displaying it
To retrieve the value, follow the recommended Android practice:
Cursor row = databaseHelper.query(true, TABLE_NAME, new String[] {
COLUMN_INDEX}, ID_COLUMN_INDEX + "=" + rowId,
null, null, null, null, null);
String dateTime = row.getString(row.getColumnIndexOrThrow(COLUMN_INDEX));
This, returns a string, parse it and reformat to your local format and time zone:
DateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
date = iso8601Format.parse(dateTime);
} catch (ParseException e) {
Log.e(TAG, "Parsing ISO8601 datetime failed", e);
}

long when = date.getTime();
int flags = 0;
flags |= android.text.format.DateUtils.FORMAT_SHOW_TIME;
flags |= android.text.format.DateUtils.FORMAT_SHOW_DATE;
flags |= android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
flags |= android.text.format.DateUtils.FORMAT_SHOW_YEAR;

String finalDateTime = android.text.format.DateUtils.formatDateTime(context,
when + TimeZone.getDefault().getOffset(when), flags);
Note the when + TimeZone.getDefault().getOffset(when) above. This does the trick to convert the UTC time/date to local time. The DateUtils.formatDateTime() seem to be supposed to do this, but it doesn't, or I wasn't able to find a way to achieve it.

And that's it.

Thursday, June 18, 2009

Interfaces, Inheritence and Hibernate

How to choose: Inheritence or Interface?
  • Idea 1: If the relationship is more an "is a", use inheritance. If it is more a "can be", use interface. Examples: TextBox "is-a" Control, ArrayList "can-be" enumerated.
  • Idea 2: If your object is a specialization of another object, use inheritance. But if the feature that distinguishes the derived class from the base class is something that other classes may need to support as well, an interface is a better choice.

Monday, June 15, 2009

Flash Builder 4, Hibernate and Eclipse: Working Together

So, we at OLCC decided to give Flash Builder 4 (beta) a try. So far, we have been working only with a small sample using the JEE for its server tier, but already have learned a few valuable lessons:

Creating a New Flex Project
  • Accept the folder names flex_src, bin-debug; the FB4 doesn't deal correctly with non-default values.
  • After creating a project, go to .flexProperties and set the serverContextRoot="/YourProjectName". After opening Properties->Flex Server window, reset this value of serverContextRoot.
  • Instead of using mx:Text, there is now s:SimpleText control.
Error 404, when trying to Debug the application

When we got this, we saw the URL that FlashBuilder is trying to use to start the HTML wrapper is http://localhost:8080/ProjectNamebin-debug/Main.html. The bin-debug definitely shouldn't be there. We also noticed, that this same URL shows in the project properties on Flex Build Path page as the Server Root URL. It can't be fixed there, but we fixed it in the Debug run configuration. Trying to use Run instead of Debug was even more messy. For some reason, it tried to connect the debugger to the FlashPlayer (yes, in Run mode).

PermGen Issue

Also, recently, we had problem with running out of the space in PermGen. The only solution we found, was to reduce its size (yes, reduce!) from the default 256M to 128M.

The funny thing is, we had eclipse running fine for a long time. Then, when we installed a 2nd instance of eclipse, using a separate workspace, we started experiencing this problem. When we used the 256M, and any serious action crashed the Eclipse, we ran the eclipsec.exe which showed an error message "not able to find enough memory to start jvm with these options" or smth like this. That's why we have reduced the memory. We haven't had the PermGen issue since then. I don't understand this issue really, it's more a trial-and-error solution, but it works.


Hibernate

For Hibernate, we use:
  • Database Development perspective provided by eclipse
  • Hibernate installed via GlassFish admin console (we pointed eclipse compiler at it)
  • Hibernate Tools from JBoss Tools (installed just the hibernate tools through the eclipse update site http://download.jboss.org/jbosstools/updates/stable/)
  • JavaDB bundled with GlassFish server
This configuration seems a good mix. That's it for now.

Tuesday, June 9, 2009

GlassFish Application Server: Introduction and More

This blog summarizes what I have found interesting or not-obvious about the Sun's open source enterprise application server called GlassFish. If you think, any of the info in this blog is not precise or just incorrect, feel free to comment.

  • Version 2.1 of GlassFish is the final version that implements Java EE 5. Version 3.0 of GlassFish is the first one that implements Java EE 6. It's a preview, but ready for production.
  • Server Domain: a new concept introduced into GlassFish that means one or more server instances that can be managed as a whole by an administrator. For developer, domain=server instance. For administrator, it can comprise of multiple, clustered server instances. Each domain, even if all domains are local, runs in its own JVM (there is also one JVM instance associated with the server administration/control, it seems). More info.
  • Virtual Server: to be finished...