Tuesday, September 30, 2008
Testing Dynamic Web Applications
At RailsConf Europe, in the Q & A portion of my talk on Functional Testing someone asked what I recommend for testing Javascript.
Ugh. Testing Javascript. Is it possible to recommend something when everything you've seen is terrible? Usually I'm cool with picking the tool that sucks the least, but when it comes to Javascript testing the only words that come to mind are: epic fail.
In the past I've failed in two different ways.
A few days later it occurred to me what the correct answer was -- Don't use Javascript and you won't have to test it.
No, I'm not suggesting that we should all go back to mostly static websites. Static content is fine for some things, but GMail is an obvious example of a site that is better done dynamically.
However, Javascript isn't your only choice for highly dynamic websites.
These days, if I were writing a website that required any dynamic interaction I would absolutely use Flex or Silverlight. I've done Flex, and it was nice to work with, but I must admit that I'm lured to Silverlight because it's going to (or does already?) support Ruby.
I'm not sure what the Silverlight testing story is, but I found Flex (and ActionScript) to be quite testable. The single biggest win (as I've said before) is that I no longer need to do in-browser testing. Removing the browser from the equation is huge. No more IE bugs causing your tests to fail, no long start up times as the browser is run, etc.
Testing with FlexUnit (with it's drawbacks) is an order of magnitude better than any experience I've had testing Javascript.
I'm comfortable saying that I would still use Javascript for trivial features that provided so little business value that they did not warrant testing. However, any features that provide noticeable business value must be tested, and I would move to a RIA solution instead.
In my experience, the benefits of switching to a RIA solution are dramatic, one of the largest being: you no longer need to worry about testing Javascript.
Ugh. Testing Javascript. Is it possible to recommend something when everything you've seen is terrible? Usually I'm cool with picking the tool that sucks the least, but when it comes to Javascript testing the only words that come to mind are: epic fail.
In the past I've failed in two different ways.
- Selenium: Too slow and to brittle for any decent size test suite. There's more on that if you wish.
- Some javascript unit testing framework. I can't even remember the name. The syntax was ugly, the tests weren't easy to write, and the runner didn't integrate with any automated tools we used -- lame.
A few days later it occurred to me what the correct answer was -- Don't use Javascript and you won't have to test it.
No, I'm not suggesting that we should all go back to mostly static websites. Static content is fine for some things, but GMail is an obvious example of a site that is better done dynamically.
However, Javascript isn't your only choice for highly dynamic websites.
These days, if I were writing a website that required any dynamic interaction I would absolutely use Flex or Silverlight. I've done Flex, and it was nice to work with, but I must admit that I'm lured to Silverlight because it's going to (or does already?) support Ruby.
I'm not sure what the Silverlight testing story is, but I found Flex (and ActionScript) to be quite testable. The single biggest win (as I've said before) is that I no longer need to do in-browser testing. Removing the browser from the equation is huge. No more IE bugs causing your tests to fail, no long start up times as the browser is run, etc.
Testing with FlexUnit (with it's drawbacks) is an order of magnitude better than any experience I've had testing Javascript.
I'm comfortable saying that I would still use Javascript for trivial features that provided so little business value that they did not warrant testing. However, any features that provide noticeable business value must be tested, and I would move to a RIA solution instead.
In my experience, the benefits of switching to a RIA solution are dramatic, one of the largest being: you no longer need to worry about testing Javascript.
Labels: flex, javascript, ria, silverlight, testing
Tuesday, July 08, 2008
ActionScript: Calling a function by name
In Ruby I can call a method using it's name (as a string) using send.
This type of behavior is helpful in scenarios where I store method names as values and execute those methods based on user actions.
In Flex I can store Objects in Views, so I generally don't need this capability. However, I recently wanted to execute a function based on what MenuItem was clicked. The menu was composed of MenuItems that were defined by XML. I couldn't figure out how to get a function into the XML, so i ended up putting the function name as an attribute of each MenuItem. From there, the only trick was figuring out how to call a function on an object if you have the name of the function stored as a string.
It turns out, it's very easy, and exactly what you do in Javascript. All you have to do is pass the string in brackets to the object that has the function defined.
If you're interested in the context, the code below is similar to what my application required.
"hello world"
end
send "hello" # => "hello world"This type of behavior is helpful in scenarios where I store method names as values and execute those methods based on user actions.
In Flex I can store Objects in Views, so I generally don't need this capability. However, I recently wanted to execute a function based on what MenuItem was clicked. The menu was composed of MenuItems that were defined by XML. I couldn't figure out how to get a function into the XML, so i ended up putting the function name as an attribute of each MenuItem. From there, the only trick was figuring out how to call a function on an object if you have the name of the function stored as a string.
It turns out, it's very easy, and exactly what you do in Javascript. All you have to do is pass the string in brackets to the object that has the function defined.
If you're interested in the context, the code below is similar to what my application required.
<mx:MenuBar id="myMenuBar" labelField="@label" itemClick="menuHandler(event);">
<mx:XMLList>
<menuitem label="Submit" handler="submit"/>
<menuitem label="Reset" handler="reset"/>
</mx:XMLList>
</mx:MenuBar>
private :void {
this[event.item.@handler](event);
}
private :void {
// do submit logic
}
public :void {
// do reset logic
}Labels: ActionScript, flex
Tuesday, June 24, 2008
Flex: Expert Developers Needed
The majority of my Flex posts have been pro-Flex. The two biggest reasons I advocate for Flex are:
I already find myself so effective using Flex that I would reach for it anytime I consider Javascript in the future. But, the world would be a much better place if the experts continued to improve upon an already solid base.
- I'm more productive with Flex than I am with HTML & Javascript.
- The Flex community could really benefit from expert adoption.
- state of testing with Flex is good enough, but it's got plenty of room to improve. (mocking framework, test runners, test frameworks, better stubbing)
- The language has dynamic capabilities, but seems to be evolving into a statically typed language.
- The majority of examples only show Flex with ActionScript in Script tags mixed with the MXML components (which is not how you need to code). I write my Flex with unobtrusive ActionScript, and it's quite easy.
- The MVC framework feels a bit too full of ceremony. I'd love to see some competition resulting in easier to use components.
I already find myself so effective using Flex that I would reach for it anytime I consider Javascript in the future. But, the world would be a much better place if the experts continued to improve upon an already solid base.
Labels: flex
Monday, June 23, 2008
Flex: Anonymous Classes as Test Stubs
In my previous post, The State of Flex Testing, I stated that I use anonymous objects as stubs. This entry will show how to easily create stubs that stub methods and properties.
If you simply need a stub that has a property, the following code is all you'll need.
The above code creates an object that response with "ready" to the message
That's really it. You can define methods and properties on anonymous objects as you please.
Is it beautiful? Not really. I've considered a few other options would allow you to define methods without the anonymous function, but it's never been so annoying that it was worth spending the time to get the implementation correct. I suspect anyone who put their mind to it could come up with a nice implementation in a short amount of time.
If you simply need a stub that has a property, the following code is all you'll need.
{state: "ready"}The above code creates an object that response with "ready" to the message
state. Adding methods is also easy if you remember that you can create properties that store anonymous functions (just like Javascript). If you need the execute method to return true, the following stub should do the trick.{state: "ready", execute: function(){ return true }}That's really it. You can define methods and properties on anonymous objects as you please.
Is it beautiful? Not really. I've considered a few other options would allow you to define methods without the anonymous function, but it's never been so annoying that it was worth spending the time to get the implementation correct. I suspect anyone who put their mind to it could come up with a nice implementation in a short amount of time.
Flex: The State of Testing
Given my focus on testing, it's not surprising that the most common question I get about Flex is: Is it testable? Of course, the answer is yes otherwise I wouldn't be using it.
Out of the box, it's very similar to early JUnit. Like all XUnit ports, it's based on creating testing classes and defining methods that are tests. There's setup, teardown, and all the usual features you expect from XUnit ports.
There's a FlexUnit swc (library) that assists in creating a test swf file, which runs all the tests in the browser. There's a few blog entries that give details on how to generate an XML file from the test swf, so breaking a build or reporting results is possible. I haven't bothered to go that far, but others have successfully blazed that trail.
In general, testing Flex is not great, but I rarely find myself concerned or unhappy. Here's a few reasons why.
I'm not a fan of manually adding tests to my test suite, but just like Paul Gross, we dynamically create ours. So it's not a problem. We didn't stop there though, we also generate the package and class name; therefore, our test classes stay pretty clean. The code below is an example of an entire test file (the ones that we work with).
Those methods wouldn't do much in isolation, but if you generate the surrounding (tedious) code, they work quite well. Here's the rake task that I use.
As you can see, I generate test files and which are later used as source for the test swf. It's a few extra steps, but I never see those steps, I just write my test methods and run
There are no mocking frameworks that I've seen, so that's kind of a bummer. Though, in practice I haven't found myself reaching for a mock anyway, but that will probably depend on your style. Again, I don't have much behavior in my views, so I don't need rich testing tools. Of course, I'd love to have them if they were available, but I don't find their loss to be a deal breaker. I do reach for stubs fairly often, but anonymous classes seem to work fine for that scenario.
There is one huge win that I'll conclude with. When using HTML & Javascript you have to test in browser to ensure that it works. This isn't true of Flex since there aren't browser issues. So, I can test my application using FlexUnit, and be confident that it just works. Removing the need for a (often slow and fragile) Selenium suite is almost enough to make me ditch HTML & Javascript forever.
Out of the box, it's very similar to early JUnit. Like all XUnit ports, it's based on creating testing classes and defining methods that are tests. There's setup, teardown, and all the usual features you expect from XUnit ports.
There's a FlexUnit swc (library) that assists in creating a test swf file, which runs all the tests in the browser. There's a few blog entries that give details on how to generate an XML file from the test swf, so breaking a build or reporting results is possible. I haven't bothered to go that far, but others have successfully blazed that trail.
In general, testing Flex is not great, but I rarely find myself concerned or unhappy. Here's a few reasons why.
- There's little logic in my views anyway, the current app is Flex front end to Rails resources.
- Anything that's annoying, I move out of my way by generating with some ruby scripts (for example: creating the file that lists all the test cases). -- more on this later
- Anonymous objects in flex have been 'good enough' stubs
I'm not a fan of manually adding tests to my test suite, but just like Paul Gross, we dynamically create ours. So it's not a problem. We didn't stop there though, we also generate the package and class name; therefore, our test classes stay pretty clean. The code below is an example of an entire test file (the ones that we work with).
public :void {
var smartListCriteria:* = new SmartListCriteria();
smartListCriteria.addLimitCriteria({order:"an order"});
assertEquals("an order", smartListCriteria.toXml().sort.order);
}
public :void {
var smartListCriteria:* = new SmartListCriteria();
smartListCriteria.addLimitCriteria({field:"a field"});
assertEquals("a field", smartListCriteria.toXml().sort.field);
}Those methods wouldn't do much in isolation, but if you generate the surrounding (tedious) code, they work quite well. Here's the rake task that I use.
desc "Generate test files"
task :generate_tests do
tests = Dir[File.dirname(__FILE__) + "/../../test/flex/tests/**/*Test.as"].each do |file_path|
file_path = File.expand_path(file_path)
package = File.basename(File.dirname(file_path))
emit_file_path = (File.dirname(file_path) + "/" + File.basename(file_path, ".as") + "Emit.as").gsub(/tests/,"generated_tests")
File.open(emit_file_path, "w") do |file|
file << <<-eot
package generated_tests. {
import flexunit.framework.TestCase;
import flexunit.framework.TestSuite;
import uk.co.company.utils.*;
import uk.co.company.smartLists.*;
import mx.controls.*;
public class extends TestCase {
}
}
eot
end
end
endAs you can see, I generate test files and which are later used as source for the test swf. It's a few extra steps, but I never see those steps, I just write my test methods and run
rake test:flex when I want to execute the tests. The one catch is that I can't run individual tests, which is terrible.There are no mocking frameworks that I've seen, so that's kind of a bummer. Though, in practice I haven't found myself reaching for a mock anyway, but that will probably depend on your style. Again, I don't have much behavior in my views, so I don't need rich testing tools. Of course, I'd love to have them if they were available, but I don't find their loss to be a deal breaker. I do reach for stubs fairly often, but anonymous classes seem to work fine for that scenario.
There is one huge win that I'll conclude with. When using HTML & Javascript you have to test in browser to ensure that it works. This isn't true of Flex since there aren't browser issues. So, I can test my application using FlexUnit, and be confident that it just works. Removing the need for a (often slow and fragile) Selenium suite is almost enough to make me ditch HTML & Javascript forever.
Tuesday, June 10, 2008
Flex: Objects in Views
Imagine the following requirement:
Flex offers you a better solution. The Flex ComboBox allows you to set the dataProvider to an array of anonymous objects which can contain pretty much whatever you need. Even if you don't know Flex and ActionScript, the following code should still be readable, and interesting.
This is one of the things I really like about Flex. Since I'm not tied to HTML and strings, I can put whatever I like in the view. The first example keeps all the logic out of the view and simply creates a new command and executes it immediately. It's nice and clean without worrying about converting from strings to classes. The second solution relies on functions to handle processing. In this case you could be doing something as simple as showing or hiding components in the view (not something you'd need a class for).
Either way, I'm working with first class concepts, instead of string representations of first class concepts. The result is cleaner code that's easier to work with.
The application needs a combo box that has the following options:Assume you are using the web. The traditional approach is to create a drop down with unique values that can be used on the server side (generally as a case statement). The unique values are strings, which represent keys, which are used to determine what the correct course of action is. This scenario works, and is familiar to most web developers, but it's not the most elegant solution.When delete is selected the current email (the one being viewed) needs to be moved from the inbox to the trash.
- delete
- mark as spam
- bounce
When mark as spam is selected the current email should be tagged as spam.
When bounce is selected the server should send a reject message to the server where the email originated.
Flex offers you a better solution. The Flex ComboBox allows you to set the dataProvider to an array of anonymous objects which can contain pretty much whatever you need. Even if you don't know Flex and ActionScript, the following code should still be readable, and interesting.
{
comboBox.dataProvider = [{label: "delete", command:DeleteCommand}, {label: "mark as spam", command:MarkAsSpamCommand}, {label: "bounce", command:BounceCommand}];
comboBox.addEventListener("change", function(){ new comboBox.selectedItem.command().execute(); });
} {
comboBox.dataProvider = [{label: "delete", execute:delete}, {label: "mark as spam", execute:markAsSpam}, {label: "bounce", execute:bounce}];
comboBox.addEventListener("change", function(){ comboBox.selectedItem.execute(); });
}
{
// delete implementation
}
{
// mark as spam implementation
}
{
// bounce implementation
}This is one of the things I really like about Flex. Since I'm not tied to HTML and strings, I can put whatever I like in the view. The first example keeps all the logic out of the view and simply creates a new command and executes it immediately. It's nice and clean without worrying about converting from strings to classes. The second solution relies on functions to handle processing. In this case you could be doing something as simple as showing or hiding components in the view (not something you'd need a class for).
Either way, I'm working with first class concepts, instead of string representations of first class concepts. The result is cleaner code that's easier to work with.
Labels: ActionScript, flex


