macdevcenter.com
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Java Programming on the Mac Getting Fit for the Holidays

by Daniel H. Steinberg
12/10/2002

In this article, we'll look at interacting with your Java programs remotely by taking advantage of the Apache Web Server that ships with Mac OS X. We'll write a quick CGI script to compile a Java program and then write a slightly more complicated script to process HTML files. Many thanks to Herb Schilling of NASA's Glenn Research Center in Cleveland and O'Reilly's Nat Torkington for their help getting the CGI scripts to do what I want. The example is taken from an upcoming book that I co-wrote with Dan Palmer on Extreme Software Engineering from Prentice Hall.

The Fit framework is another great idea from Ward Cunningham. You can read more about it and download it at fit.c2.com . Before looking at the CGI scripts, I want to talk briefly about the Fit framework. It's such a cool idea and much simpler than the solutions that many of us have been playing with for writing and automatically running acceptance tests. As always, suggestions for future articles and comments can be sent to me at DSteinberg@core.com.

Playing with Toys

At least once a day someone ducks into the office of one of my colleagues and makes some comment about the two Macs on his desk. He teaches computer science at a local university and used to run Windows and Linux but now has a TiBook and an iMac. Once each day he listens as someone derides his choice of a "toy machine."

I ask him what his answer is, and he shrugs and responds, "What's the point?"

"What's the point?" I exclaim. "The point is that your Mac ships with Java, Ruby, Python, and Perl. The point is that you can open up a Terminal window and edit using vi or emacs. You can set up sendmail or use lynx. You can enable the Apache Web server that ships with every Mac by checking a check box. That's the point."

"I usually tell them that," he says, "but then they ask me if they can play the latest version of some game on it like they can on a Windows box."

"Well then," I reply, "which one is the toy machine?"

I've been thinking a lot about toys lately, and I've reconsidered my position. The Mac is a toy. Mac OS X is a totally decked out toy for developers. In the old days I would go to conferences and see the latest technology and know that it would be years until I'd see a Mac version. In fact, I first got into the business of covering Java on the Mac because Apple's releases always lagged so far behind the corresponding Windows release. Sure, Java 1.4 still isn't final, but you can download regular releases of the Developers Preview for free at the ADC site . We'll talk more about why the upcoming Java release is special in a future article.

Last month I went to Seattle for the Ruby developers' conference and for the annual OOPSLA (Object Oriented Programming something something something ) conference and then on to Dallas for the Lonestar Software Symposium. The first thing that struck me at all of these conferences was the growing percentage of Macs that were around. If Macs still represent only about five percent of the market, then they are way over-represented at developers shows these days. Ruby inventor Matz said that he is pleased that Ruby is distributed as part of Jaguar but that no one from Apple ever contacted him. In Dallas, different developers used different IDEs from IDEA and Eclipse to ProjectBuilder and command line tools. At OOPSLA, Martin Fowler mentioned a new framework available for supporting acceptance testing.

What Is Fit?

The Fit framework allows business people to specify what software should do or how it will behave in simple tables. These tables are meant to be embedded in HTML or Wiki pages. The tables are then tied into the application that they are testing by fixtures that extend and use the classes provided in the framework. What makes this framework even cooler is that a customer can run the acceptance tests remotely just by clicking a hyperlink in a browser. The focus of this article will be setting up the CGI scripts to remotely process the HTML pages. In the next section, you'll get a taste of what Fit is all about.

Understanding the Fit Framework

First, let's imagine that you're building a cash register program. If you enter the unit price in pennies and the number of items purchased, then you'd like to verify that the total cost for that particular item is correct. Your table might look something like this: (You can view source if you need an HTML refresher.)

register.CaseDiscountFixture
unitPrice numberPurchased itemTotal()
800 1 800
800 5 4000
800 12 9120
800 17 13120
800 24 18240
800 29 22240
800 1200 912000
4 12 46

For example, in this table the items in all rows except the last one are priced at $8 each. The first row helps you confirm that the price of one item is $8, and the second row helps you confirm that the price of two items is $40. The third row doesn't seem right at first. Your client is trying to verify that a 5 percent discount is given for each set of twelve purchased.

One of the advantages of the Fit framework is that the tables are easy for the clients to create and for the developers to process. In this case, the developers have indicated that the Java class that will be used to process it is called CaseDiscountFixture and that it is inside of the register package. This particular fixture extends the ColumnFixture class that is part of the Fit framework. In this case, each column of the table will map to a different member of the CaseDiscountFixture class. The first two columns will be inputs and correspond to variables, the third column is the expected return value from a method call. The CaseDiscountFixture class will need to contain variables named unitPrice and numberPurchased of type int and a method named itemTotal() that takes no arguments and returns an int .

Here's a look at one possible example of register.CaseDiscountFixture .

package register;

import fit.ColumnFixture;

public class CaseDiscountFixture extends ColumnFixture{
  public int unitPrice;
  public int numberPurchased;

  public int itemTotal(){
    Item item = new Item(unitPrice);
    item.addToOrder(numberPurchased);
    return item.totalItemCost();
  }
}

Notice this creates a new instance of type Item and sends it messages. If you'd like, for now you can replace the body of itemTotal() with this return statement.

 return unitPrice * numberPurchased;

In practice, you would use the first approach, but this second, stubbed out version will allow you to easily experiment with the framework without creating all of the supporting classes.

As a second example, let's look at a table that models how you might control a GUI. Here you'll model pressing buttons, entering information, and checking the results. Continuing the cash register example, this might represent manually entering the price for an item that can't be scanned.

fit.ActionFixture
start register.MiscItemFixture  
press miscButton  
check display Enter Unit Price
enter unitPrice 800
check display 800
press enterButton  
check display Misc Grocery 800
press timesButton  
check display Enter number of items
enter numberOfItems 5
check display 5
press doneButton  
check display 4000
check totalCost 4000

In this case there are four keywords recognized in the fit.ActionFixture class: start , press , enter , and check . The press keyword is used to simulate a button press. In this example you can see that there is a miscButton , enterButton , timesButton , and doneButton . These will correspond to method calls -- not in the ActionFixture class but in the register.MiscItemFixture that is instantiated with the start keyword. The enter keyword also calls methods with names specified in the second column with values passed in the third column. Finally, the check keyword calls the method in the second column and compares the return value with the value in the third column.

Pages: 1, 2, 3

Next Pagearrow