Wednesday June 17, 2009
The new iPhone 3.0 software was released a little under an hour ago. The upgrade was trivial. I clicked the Check For Update a few minutes after the release, and it downloaded the new OS in around 3 minutes! I recently switched ISPs so I have really good bandwidth now - but I had expected a lot of traffic on Apple's servers to slow things down.
The update looks really good. I tested a few of the things I have been looking forward to -- I personally don't care about the feature highlights listed on most sites, such as MMS, Copy and Paste, etc.
The first feature I've been waiting for is the ability in the browser to open a link in another window. With tabbed browsing I'm used to just ctrl-clicking on links such that pages load in the background, and when I'm done with the current page I go read the other tabs which by then are fully loaded. On the iPhone on the other hand I haven't been able to do this, since there hasn't been a way to open a link without throwing away the page you're on. But in 3.0, it's there - just click and hold a link and you get the option to open the link in a new page. It's not as good as tabbed browsing - it instantly jumps to the new, not yet loaded page, but it's trivial to jump back and keep reading while the new page is loading.
The second feature I've been waiting for is improved iPod controls. The primary usage for my iPhone is as an iPod - while running, doing chores or driving - and I listen to a lot of podcasts. With 3.0, the scrubbing feature is improved - it's now a lot easier to jump to arbitrary points in the podcast. I like to listen to This Week in Technology for example, but I'm getting really, REALLY sick of the 5+ minutes of Audible commercials in each and every episode. This is the DVR generation -- if a commercial is longer than 30 seconds I'm going to start resenting you. In 2.0 it was difficult to either fast forward (too slow, then too fast) or jump to arbitrary points in the podcast. With 3.0 it works really well - I just place my thumb on the scrollbar and lean it to the right then left to tweak the final endpoint.
Another iPod improvement is the ability to play podcasts at a faster rate. For the Java Posse some volunteers (thank you!) set up a server which would download our podcasts, apply audio processing to speed up the podcast, and then release these as faster versions of our episodes - called the Tempo Posse. This is no longer necessary with 3.0 - there's a button you can click to cycle between half speed, full speed and double speed playback:
I don't think this will run the Tempo Posse out of "business", because I looked at our download stats the other day and nearly half of all episodes are downloaded outside of iTunes! Are there really that many Zune users? ;-)
Tuesday June 16, 2009
(See intro for a background and caveats on these coding advice blog entries.)
I came across a JavaWorld coding-advice article the other day. While the thread which led me there referenced the second point of the article, I couldn't get past the first one where the author argues that
...a reader needs to know which items are local variables, which are fields, and which are method arguments. [...] It's likely best to use a simple naming convention to distinguish between these three cases.
Monday June 08, 2009
We lifted the veil on the new designer tool for JavaFX last week at the JavaOne 2009 conference. Here's a screenshot:
The tool made a number of appearances:
I've scanned the blogosphere and twitter for comments on the tool and demos and the feedback is very positive.
Here's
a particularly detailed blog post with pictures and video snippets detailing the Friday demo.
Now we just need to finish the feature set, fix the bugs and polish everything! It's been a sprint for the whole team to get to this point. But we're not building a demo! We're building a product! So we're not getting much of a rest, it's right back to work to finish this thing!
(Photo by Balz Schreier)
P.S. In case you missed it, Larry Ellison from Oracle went on stage and made several comments regarding JavaFX in case the acquisition should happen - here's one article, there are many others.
P.S.2. We had our fourth annual Java Posse BOF live recording session last week. It was a blast. Dick stayed up editing and releasing
the podcast
the same night. If you're wondering what happened in the middle of the episode, where there's not much audio and a lot of laughing, that's me nearly drowning. I took a big swig of beer just as Joe made a joke; the beer went down the wrong tube, and then I was laughing so hard I couldn't breathe. My eyes were runny and I had beer all over my face and chest. Pretty embarrassing but reportedly also entertaining for others! Here's a photo from our get-together at a bar afterwards:
(Photo by Toni Epple)
Thursday May 14, 2009
I like unit tests - but running them can be painful. Commit-validation tests
which bring up UI are obviously annoying, but even simple unit tests that
get in the way. Does this look familiar?
The above menubar should look familiar to anyone on a Mac who's run unit tests for client side
Java code. Not necessarily GUI tests, just any test where GUI libraries are loaded.
For every testcase, the test runner fires up a new process, which tells
OSX that "I'm graphical, give me focus!", and this steals the focus from the user.
The test finishes quickly thereafter, the process quits - and then the test runner
goes to the next test and the whole cycle starts over.
This is really painful because I like to have lots of tests. The Python editor support
for Netbeans had 600+ tests;
the counts for the JavaScript support was higher, and
the Ruby support even higher than that. Whenever I run tests, I basically have to
fight with my computer to get focus. Forget trying to write anything - every second
or so my keystrokes get stolen as the next test grabs focus - so I've gotten in
the habit of using the time for browsing, since I'm mostly reading, and I can handle
clicking a link a second time if the first click got lost. But every now and then
somebody will ping me on instant messaging - and it's maddening trying to respond while
this is going on.
If this is sounding painfully familiar to you, I have good news. I've finally figured
out a setup where this is no longer a problem!
The key discovery was that I can run my tests from another account on the system.
With OSX' fast user switching, I can switch to the alternate account, launch the
unit tests, and return back to my regular account where the tests won't interfere
with display focus. In order to let me run my tests from that other account, I
just open a terminal there and su -l tor in the shell to run all the
commands (or NetBeans) as myself.
This was a huge improvement since it removes the 10-30 minutes testrun downtime. But it had some disadvantages - first, I don't like running tests from a shell, and second, it's hard to know when things finish - and switching back and forth to check is annoying since I always have passwords on my accounts so the machine isn't open.
So the second step was to set up Hudson (a
continuous integration server that is trivial to setup, and has a huge number of
plugins which makes
graphing code coverage, unit tests, findbugs results, integrating with version control
systems etc trivial. And it's
not just for Java developers.)
Instead of logging into the other account
for each test run, I log into the other account once, and start up Glassfish
with Hudson running. From now on I can access, configure and launch builds right
from my own browser in my primary account. The key step here is that Glassfish was
started from the secondary account, so its primary display is associated with the builder account.
When my build in Glassfish gets to the test stage, it's actually doing the display
connection just as before, and if I log into the secondary account, I get the annoying
focus flashing just as before. Look - the tested process is a user visible application in the dock:
Another improvement which really helped is the "File System" version control plugin for Hudson.
I want my Hudson builds to build my current working copy. I don't want to
check my code into Mercurial (even a local repository) just so that Hudson can
grab the code and build it. I want Hudson to build my current changes - my current
edits. After all, I'm trying to test them before checking in! And I discovered that
there is a plugin which will let me do that - it's just
a "file system" version control wrapper - which means you just point Hudson to your local
directory, and off it goes. When the build starts, it makes a quick disk-copy of the
source tree. Even though Mercurial cloning is pretty fast, this is even faster.
The disk copy also lets me specify a filter of files to exclude, so I had it ignore
*.class files. The diskcopy only takes 10 seconds or so before the build kicks
off, and it's building a snapshot of my current in-progress, edited working copy!
(It can also just update the copy based on changed filestamps - that's even faster,
but it didn't seem to correctly delete removed files, so I let it start from scratch
each time.)
(Note - this plugin isn't in the catalog that you can browse right from within the
Manage Plugins page within Hudson; I downloaded the .hpi file from
http://wiki.hudson-ci.org/display/HUDSON/File+System+SCM
and installed it in the Advanced tab.)
The final ingredient is the new Hudson support in NetBeans 6.7. I don't even have
to go to the browser to kick off build jobs. I just point NetBeans to my Hudson
server once, and from then on I have full Hudson integration. When I want to
run my tests I just select Launch job:
I get notified if there's a problem:
I can look at failures and logs:
I can see build logs etc. directly in the output window, and hyperlinks warp to directly to files - to the files as they were in the build, not the current state:
So to recap - with this setup, as I'm editing my code and I want to check the tests, I just right click on a node and say "Start Job" - and off it goes without bothering me at all - no more focus interruptions, and no more GUI windows popping up from interactive tests. It's trivial to check the results. And it's even added one more level of convenience: I have multiple projects, each with unit tests, and from the IDE I couldn't have them all run with a single gesture. My build job does that.
I'm really stoked! I was at one point able to do this when I was working on Linux and Solaris by setting my $DISPLAY variable and doing tricks with VNC. But that still required my tests to run in a console - which made interpreting the results sucky.
If you haven't played with Hudson, try it - it's unbelievably easy to set up. Just download
the Glassfish appserver and install it, download the Hudson .war file, and drop the hudson.war
into the autodeploy directory of the appserver, and browse to localhost:8080/hudson.
Once you're there you can install
plugins (under Manage hudson), point to your local installations of the JDK, ant,
etc., and configure your build jobs by running scripts, launching maven scripts, writing
ruby scripts, or obviously running ant scripts.
Some final miscellaneous tips:
~/.hudson/jobs/ directory.
.hudson) in its file chooser. Here's a tip I didn't
learn until recently: When a Mac filechooser has focus, you can press slash (/) - and this
will open a text field where you can directly type the path it should jump to. I typed
/Users/tor/.hudson and from there I was able to select the jobs directory to exclude.
ant in the past where it decided to follow symlinks in its
zeal to delete recursively!
Tuesday May 12, 2009 As I was working yesterday my laptop felt kinda wobbly. I didn't think too much about it. But it started getting annoying. I lifted the laptop and looked under it to make sure my laptop wasn't accidentally sitting on top of a USB cable or something like that. Nope.
A little while later I was getting really annoyed - so I flipped the computer all the over to see what was up. And to my surprise my battery was completely warped. It looks like it had "exploded" sometime this weekend. Check out how warped it is:
A couple of years ago one of my Apple power supplies would make humming noices now and then, and one day I happened to be looking at it when it shot some sparks! Luckily I had a floor mat so any previous sparks hadn't ignited the carpet. I got that adapter replaced. But I'm definitely thankful neither incident caused fires!
(2009-05-12 17:07:04.0) Permalink Comments [2]
Wednesday April 29, 2009 The NetBeans support for editing JavaFX isn't as mature as for other languages. After working with it for a little bit I've figured out a few things you might find helpful:
DropShadow. Not knowing
where it lives I would just type DropS to get NetBeans to show it to me and also import it for me (and advantage
of using code completion instead of just typing the name). But that just didn't work - after typing DropShadow and
attempting code completion it wouldn't show me any matches!
Monday April 27, 2009 I work from home, so I rely heavily on Instant Messaging and IRC to communicate with my co-workers, and for video conferencing I use Skype.
I sometimes make typing mistakes. And if the typo is particularly embarrassing, to the extent that I want to fix it to show that I know better, I usually write something like this:
12:00 I agre. 12:00 s/agre/agree/Anybody with
vi experience or even sed experience will recognize the second line as a search/replace command, so I'm really saying "I said agre but I meant agree". It's reflex at this point - I'll do it for the most minor accident.
I usually only use Skype for video conferencing, not instant messaging. But I just discovered, by accident, that Skype does something wonderful. Instead of showing my substitution command, it applies it to the previous line, instantly, on both sides of the conversation! Look at this:
Ugh, typo, reflexively type s/foo/bar
Voila:
Instead of adding my correction command to the log for the viewer to interpret, it just edited the previous command in place. If I can type this quickly enough, perhaps the reader won't notice!
Chatzilla, Adium, Others - Please please please do this too!
P.S. On the topic of terminal conventions.... I like using ^H's as a "just kidding" device:
12:00 Ok, I'll slap^H^H^H^H tell him about it.Anyone who's logged into terminals with wrong tty settings will recognize the ^H's as failed backspaces... And I don't want IM clients processing these :) (2009-04-27 13:34:28.0) Permalink Comments [3]
Friday April 24, 2009 A lot of stuff is happening these days, so here are some quickies... is this what people use Twitter for?
Yesterday was "Take Your Daughters and Sons to Work Day", so I brought my kids down to the Santa Clara campus. They had a great time. After "working" in an office while I was on my laptop, we walked around the campus, they met my boss, and I'm sure the highlight for them was having lunch in the Sun cafeteria - which even had a special kids menu for the day. In our walk through some of the buildings we came across a pool table where they got to try pool for the first time.
My friend Carl Quinn just got his Tesla - an all electric super sporty car. He's waited two years or so since he ordered it and they're just now coming off the assembly line. When we got together for a podcast recording session Wednesday night he brought the car, and took each of us for a spin around the block. Wow! It felt like like getting a ride in a fighter jet - but while the acceleration force was amazing, unlike a jet the all electric motor is unbelievably silent. I can't wait for cars like these to get to mass market! There are some pictures of our rides on Jackie's blog, and Joe has a lot more pictures and even some video.
Tuesday April 07, 2009
The Flubber application I described earlier has an old stop-watch style timer with second and minute hands:
Making the clock hand move was trivial using value binding and a rotation transform on the hand graphics object:
transforms: Rotate {
angle: bind (360.0 / 60 * minutes) - 90.0
}
Since we are using a binding expression, setting the minutes variable anywhere (and yes, assigning to it!) will cause the hand angle to be recomputed and the graphics updated.
effect: DropShadow {
offsetX: 5
offsetY: 5
color: Color.BLACK
radius: 10
}
That looked pretty good:
effect: DropShadow {
offsetX: bind Math.sin(Math.toRadians(handAngle + 45)) * 5.0
offsetY: bind Math.cos(Math.toRadians(handAngle + 45)) * 5.0
color: Color.BLACK
radius: 10
}
Now, the drop shadow offset moves along with the rotation such that the shadow always appears in the right place.
It worked, and we moved on.
Now that I understand JavaFX and the scenegraph a bit better I realize that this approach is wrong - there's a much simpler solution!
We don't want to apply the drop shadow to the Path object directly, since the path is what we are rotating with our minute angle.
Instead, we should simply move the effect out to the surrounding parent. That will apply the drop shadow after the shape
has been rotated.
Doing that, we can set our drop shadow initialization back to the original simple 5,5 delta, and we get exactly the result we want:
So, think about which node you apply effects to! And by the way, the effects framework is really fun to play with - you should definitely
explore javafx.scene.effect.* !
Monday March 23, 2009 At the Roundup a few weeks ago we rewrote the old Swing JFlubber application to JavaFX. We had a brand new graphical design done in PhotoShop, and we hooked up the functionality with some swanky effects. I might get into that in another blog entry.
But one challenge we ran into was that of displaying text. In the Flubber application we need to have an editable text area where flub times are automatically inserted and the user can add additional comments. JavaFX makes it easy to throw some simple text in a design, but edit, scroll, and so on? Not yet.
Proper GUI components for JavaFX is coming. But in the mean time, there are some tricks you can use. Put simply, you can use a Swing text area, but without looking like Swing. Here's how. First, create a JavaFX scenegraph node for the Swing text component:
var textPane = new JTextPane(); var scrollPane = new JScrollPane(textPane); var text: SwingComponent = SwingComponent.wrap(scrollPane);Let's see how that looks:
textPane.setBackground(new java.awt.Color(0,0,0,0)); // 0 opacity => 100% transparent! textPane.setForeground(java.awt.Color.WHITE); textPane.setCaretColor(java.awt.Color.WHITE); scrollPane.setOpaque(false);Let's try again:
scrollPane.setBorder(new EmptyBorder(new Insets(0,0,0,0)));
textPane.setFont(new java.awt.Font("American Typewriter", 0, 14));Here's what we get:
import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import javax.swing.JTextPane; public class AntiAliasedTextArea extends JTextPane { @Override public void paint(Graphics g) { Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); super.paint(g); } }Now we can just change
var textPane = new JTextPane();to
var textPane = new AntiAliasedTextPane();and we get this:
But there is one more problem... What if we add a lot of text:
Scrollbars! We don't want those. This text pane won't be used for much text, so you can just move the caret around like in a text field to navigate the overflow content. So let's turn off the scrollbars:
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);and with that, the text pane behaves exactly the way we want. Now you can manipulate text in the usual way:
textPane.setText(string), textPane.getText(), etc.
While we're at it, let's fix the selection colors as well such that when you select text you don't get the telltale Swing light blue:
textPane.setSelectionColor(new Color(255, 255, 255, 50)); textPane.setSelectedTextColor(new Color(255, 255, 255, 255));Note again how we can use transparency on this colors to give a nice glass effect on the selection (I also bumped up the font size):
Monday March 16, 2009 At the Roundup last week I talked to Robert Cooper, who's doing a lot of interesting work with GWT (Google Web Toolkit). In GWT (which compiles Java to JavaScript), you can embed JavaScript directly within the Java files inside comments with special markers. Robert mentioned that IntelliJ has a nice feature for GWT programmers where your native JavaScript snippets get JavaScript highlighting etc.
I figured that would be a trivial thing to add to NetBeans with our language embedding infrastructure. Sure enough, the patch just adds 13 lines of code. Here's a screenshot - showing JavaScript (regular expressions etc) inside Java code (with packages etc) - it's inside comments that start and end with -{ and }-:
If you want this functionality in your own 7.0 build, just download this module nbm, or apply the patch to your own build.
(2009-03-16 10:37:17.0) Permalink Comments [6]
Thursday March 12, 2009 I just got back from the Java Posse Roundup 2009. It was our third year (blog entries from 2007, 2008), and therefore I can add "as usual" when I state that it was a wonderful time.
This year's topic was "developer productivity", which is obviously a passion of mine, so I found all the technical sessions thoroughly enjoyable. We recorded all of them so they will be released slowly through the regular podcast channel.
I was able to redeem myself from last year's skiing disaster but not falling doesn't make very compelling video...
Another highlight is the lightning talks. This year we had two hours of lightning talks every night. We'll be releasing those on a quicker schedule as YouTube videos in our YouTube channel. I can recommend Barry Hawkins' talk as a starter. The nice thing about lightning talks are that they are short so go ahead, give it a try!
In order to enforce the 5 minute rule for lightning talks, we wrote a little timer app, as seen in this picture:
The laptop on the left is running our downcounter. It starts at 5 minutes, and when it gets down to 0 it plays a sound effect which politely asks the user to, ehm, stop. We wrote this app as a collaboration on the first day of the conference, during the language dojos. We had 3-4 sites where different people studied Scala, Groovy, Python, Fan and JavaFX, according to their interests. In the JavaFX group we played around with the language in the morning, and then decided to build something real - the countdown timer. We needed a sound effect to play when the timer expires, so we held up one of our conference audio recorders and all at once yelled "Shut Up!" into it. In the room next door Dick Wall had just started talking about Scala, and our brief recording session apparently caused some confusion...
P.S. There are a lot of pictures from the Roundup on flickr. The below are by Joe Nuxoll.
Crested Butte, Colorado by night:
The first day of the Open Conference we held a languages-on-the-JVM dojo. This is a picture of those of us playing with JavaFX:
The lightning talks schedule for the Tuesday night:
On Thursday we had a progressive dinner where each household served one course for the other participants. Carl made Indian Style chicken wings and Ido is getting ready to serve:
Dick and Dianne talking during the progressive dinner.
Wednesday March 11, 2009 Apologies for the recent blog silence for me. It's not that I've been slacking off. Quite to the contrary! The biggest news is that I've changed teams: I'm now working on JavaFX! And more specifically, the designer tool.
If you don't know what JavaFX is, you're probably reading my blog because you're interested in Ruby, Python or the various other languages for NetBeans I've been involved with. If so, fear not - NetBeans language support is in great hands - Erno just improved the Rails dynamic finders code completion for Ruby for example. Of course, as an open source project we can always use more contributors! I've received a bunch of patches for the Python support recently which I've been happy to apply immediately. Keep 'em coming!
Briefly, JavaFX is a new UI stack for Java which makes it trivial to build pretty, dynamic and interactive UIs. While Java has always made it easy to target multiple operating systems, JavaFX makes it easy to target the completely separate platforms of desktop, web and mobile. If you haven't looked into it, you should.
JavaFX has its own language, JavaFX Script. It has some language level features which makes it really suited to building UI applications - from something simple like a literal for durations (so you can write 2m or 5s or 250ms in your source code), to something advanced like variable bindings which give you all of the power of traditional property change listeners, but without the pain (and it's more powerful than that - you can for example bind the rotation angle of a clock hand to an expression which computes the angle from the current time, and whenever the time variable changes the clock hand rotation is updated.) As a Java developer (and a Ruby and Python and JavaScript coder as well) I can truly say I've seen some things in JavaFX Script that I would like to see in other languages. I might talk about that in an upcoming blog entry.
If you're one of the alternate-languages-on-the-JVM people, I think you should seriously look into adding a binding layer for the JavaFX platform to your language. Libraries like Groovy Swingbuilders (and similar libraries for Ruby etc) have made Swing more accessible, but at the end of the day you're still dealing with Swing. If you want to add drop shadows, transition animations etc. a JavaFX DSL would be a much better approach. And besides, we're firing on all 256 cylinders on the JavaFX platform -- from the base Java platform (adding modularity so we can provide a barebones FX runtime), to the graphics system, to components, to the language, and up to the designer tool! I think it's going to shake up the RIA space - which is why I wanted to be part of it.
I promise my next blog entry won't be long in waiting, I've got a bunch of things queued up!
(2009-03-11 18:47:37.0) Permalink Comments [7]
Tuesday January 13, 2009 Python and Ruby are dynamically typed languages. We have a lot of heuristics in our editors to figure out the types - tracking assignments, analyzing your database migrations, etc - to help code completion, go to declaration and other IDE features work correctly. And Martin Krauskopf, who owns the Ruby editor now, has been improving the type inference for Ruby a lot lately.
However, there are cases where we just can't help. What if you're writing a brand new method you haven't called from anywhere, and you're trying to access methods on one of your parameters? We don't know the type of the parameter. In that case, NetBeans will provide "fallback code completion" - it will list ALL methods across ALL known classes in your project, libraries and current platform.
If you're looking for the documentation or parameters for a specific method - that's useful - after typing 2-3 characters you've typically narrowed the result set down to a handful of methods and you can pick the one you're looking for.
But what if you're not sure what the method is called? That exact scenario happened to me a couple of days ago. I was writing some Python code to do some string manipulation, and not being very familiar with Python I wanted to know what the equivalent of Java's indexOf method was in Python. I knew that the parameter in my method was a String, but I didn't have a way of telling the IDE that. I applied my usual workaround of adding a line above the current call:
x = ""and then I could invoke
x. to see the methods available for a String. However, that's definitely not a good way to do it. What if I forget to remove my fake assignment? (Yep, I did that too. I couldn't figure out why my code wasn't working until I debugged and realized I was clearing out the parameter with a bogus assignment... Doh!)
The "obvious" solution for this is supporting type assertions. We've had those for a long time in the Ruby editor
(picture), and obviously for JavaScript using the @type and @param {type} syntax. And the PHP editor just added support for type assertions as well (more here and here).
I've just added this for the Python editor as well. But I've gone one step further which I think makes the feature much more obvious, and easy to use. In code completion, if the editor detects that you are attempting to complete on a simple variable (as opposed to for example a complicated expression), and the type of that variable cannot be resolved, then we add a new special code completion item at the top of the list. Here's what it says (and a more detailed explanation in the documentation popup):
As soon as you press enter, the IDE will insert a special comment referencing the variable you were completing on, and automatically invoke code completion again to complete on the type statement:
The contents of this list has two parts: First, it lists the pseudo-types for many of the core builtin types, like ints, strings, lists and tuples. After that it will list all the known types in the system, such as the user and library classes. If you select one of these and try code completing the original expression again, you can now see that the type resolver knows what to do:
A couple of notes about this. First, note that the type assertions are just comments in your source. You can delete them - they are merely an aid to the IDE. Not only code completion uses these - go to declaration for example will also be more accurate if it is explicitly told the type of a variable it cannot figure out. You can also use multiple type assertions within a method in case the variable type changes during the method. This isn't the case with Ruby yet; the type assertions apply to parameters only, at the method level. But Martin has promised to look into this for Ruby as well so hopefully there will be full parity between the two editors shortly!
P.S. Just like in the PHP editor, mark occurrences and instant rename are type-assertion-aware:
Monday January 05, 2009
In the 7.0 builds, we have a dedicated unit test runner for Python now. Running a file as a test, or running the test project action, will open a test runner with the output docked on its right hand side, instead of just the output window (click for full size screenshot):
Here's the test runner itself:
What you want to see in the output is a single green line which says "All n Tests Passed", where n is hopefully a large number. But when one or more of the tests fail, you see something like the above. Running the Next Error action (Cmd-.) will jump to the next failed test, just like it normally jumps to the next error in the current output window, or the next task in the tasklist.
One thing to notice (and this is new in 7.0) is that we now include the failure message right there in the test summary for each test, so you don't have to drill into an individual test to see the failure message. You can also hover over a test and any output from that test is shown in a tooltip. You can also right click on tests and select "Run Again" to run just one specific test over again.
This is the same window as the one we have for Ruby. In fact, Erno, who wrote the Ruby test runner, has modularized the code now such that it's the same implementation for both languages - we just have language specific plugins to actually hook into the various testing frameworks. Currently, for Python we support the two builtin testing frameworks: unittest and doctest. The above screenshot showed a regular unittest run. Here's a doctest:
One important thing to note is that you don't have to instrument your code with any test running code. As long as you place doctests in your docstrings, or as long as you have any classes extending unittest.TestCase, the test runner will find them. All you have to do is run Test Project:
and when you have done that, both unittests and doctests are found and included in the same test run - here's both failing doctests and unit tests:
Once again, kudos to Erno for writing the excellent test runner support! And as usual, let us know of any problems.
P.S. Jean-Yves Mengant has also done some excellent work recently. In addition to some cool new quickfixes in the Python editor for NetBeans, he has just integrated a multithreaded debugger for Python!