Wednesday, December 10th, 2008

Common Feature Tests

Category: Testing

<p>Kangax has written about his new Common Feature Tests project:

I have been working on a little personal project of mine for the past couple of months. It’s called CFT and stands for Common Feature Tests. There’s nothing really ground-breaking about it; CFT is simply a set of so-called feature tests for Javascript (or rather for any ECMAScript-compliant flavor – be it Microsoft’s JScript, Mozilla’s JavaScript or WebKit’s JavaScriptCore engines).

These tests aim to detect all kinds of quirks that modern (and not so modern) browsers exhibit and detect those quirks in the most straight-forward way – using feature detection rather than browser sniffing. There are quite few excellent resources out there on a subject of “browser sniffing vs. feature detection”. It’s definitely worth checking them out.

CFT started as an initiative to replace as many unnecessary browser sniffing from Prototype.js as possible (now that I’m part of the core, I feel bound to do something useful for the library :)). The suite was then extended with other tests that seemed not quite trivial to implement.

I really hope CFT helps developers eliminate browser sniffing code plaguing their scripts. The project is under an MIT license and is hosted on github (although is still in its infancy).

You can walk through the tests to see results, and show the code, such as “WINDOW_EVAL_EVALUATES_IN_GLOBAL_SCOPE”:

javascript
< view plain text >
  1. function () {
  2.   var fnId = "__eval" + Number(new Date), passed = false;
  3.   window.eval("function " + fnId + "(){}");
  4.   passed = fnId in window;
  5.   if (passed) {
  6.       delete window[fnId];
  7.   }
  8.   return passed;
  9. }

Related Content:

Posted by Dion Almaer at 8:34 am
22 Comments

++++-
4.2 rating from 19 votes

22 Comments »

Comments feed TrackBack URI

Nice work, if these tests go into Prototype it could be nice to feature test for browsers as well to replace all the sniffing.

Comment by lovejs — December 10, 2008

Off to a great start kangax. Keep up the good work :D

Comment by jdalton — December 10, 2008

Neat stuff kangax. It’ll be very useful once this makes it’s way into Prototype.

@lovejs: a browser isn’t a feature, a good set of feature tests could help to avoid browser sniffing/detection altogether.

Comment by staaky — December 10, 2008

Pretty cool. Although you have to be careful of how long these kind of tests take to run, especially when they involve regex, adding / removing events, eval etc etc.

As the list of tests grows, the browser sniffing becomes the faster option.

Jake.

Comment by jaffathecake — December 10, 2008

It seems to me that the popularity of the libraries themselves have already guaranteed that browser sniffing will work.
.
Take Chrome. It worked pretty well right out of the gate because they tested it against a myriad of web sites. Who is going to release a browser that crashes on jQuery sites, for example?
.
Right now I have the opposite desire. I’m writing an AIR app. I’m using jQuery and I think all the checks in jQuery are silly, because I know the environment I’m running in and jQuery keeps checking all these little things all the time. A stripped-down jQuery would be smaller and faster and less complicated.

Comment by Nosredna — December 10, 2008

Very nice work, Kangax!

But heh, the other day I had a very similar idea to make a tool for convienient manual gathering of information about what javascript code works on which browsers. Here’s the rough result: http://javy-labs.com/jsCaps/

Comment by tahu — December 10, 2008

Well, most of the bugs and missing features are IE only… did anyone expect something different? Why create a series of tests, if it is enough to suspect IE to misbehave?

Like Nosredna, I would like to see JS libs without all the sniffing and feature detection for special cases like AIR or Titanium appliactions. JS libraries should be available in optimized versions for webkit or… well, webkit it most popular for being used for stand alone web based applications.

Comment by AndiSkater — December 10, 2008

@Nosredna, AndiSkater; not trying to plug, but to my knowledge MooTools does a pretty good in this arena (since you can exclude Browser.js module). I believe Dojo (and Ext?) has similar extensibility — eg, that it’s easy to work in Air.

Comment by ibolmo — December 10, 2008

Thanks for all the positive comments.

@jaffathecake
While some of the tests involve relatively complex manipulations, their total execution time should be close to nothing. The whole suite, for example, finishes in ~16ms in FF3 and ~50ms in IE6. Even though sniffing `userAgent` string is much faster, it’s not even close as reliable as a proper feature test : )

@Nosredna, @AndiSkater
Actually, I remember many scripts failing in Chrome once it came out : )
There should be no doubt that feature detection is simply the sanest way to design client-side scripts. It’s not about any particular browser and which `userAgent` it implements. It’s about doing something that makes sense (feature detection) instead of relying on baseless sniffing and getting into troubles in a long run.

Comment by kangax — December 11, 2008

Yeah, I see that your implementation is fairly speedy, although many more tests would be needed for a large javascript library. It will be interesting to see how long it takes and how heavy it is when it covers all/most of Prototype’s browser sniffing.
.
An example I always drag out is Node.contains in Safari 2, which misbehaves. You could feature detect for this by create a tree of nodes and unit test Node.contains to see if it works as expected, but that would be quite expensive.
.
And if you’re unit testing that a function behaves, shouldn’t you be doing that with all DOM functions, in case a browser comes out which has a bug in a function? No, we’d only test Node.contains because we know there’s a problem with it in Safari.
.
But… if we’re only testing it because there’s a problem with it in a particular browser, why not just detect that browser (which is quicker and lighter). Obviously doing sniffing based on WebKit version covers other WebKit browsers.
.
Although I think your work so far is fantastic, and many of your constants should be used rather than resort to sniffing, it’ll be interesting to see where you draw the line.
.
Jake.

Comment by jaffathecake — December 11, 2008

This is the worst feature testing code I have ever seen. Except for the isHostMethod function at the top, which was lifted from My Library.

http://www.cinsoft.net/mylib.html

And even if you lifted all of the feature testing, Prototype would still be a shambles. It isn’t even worth talking about.

And yes, browser sniffing can be much faster than feature testing. LOL. Incompetent, technically baseless and ten years behind the times, but fast.

Comment by DavidMark — December 11, 2008

Somebody wrote:

“It seems to me that the popularity of the libraries themselves have already guaranteed that browser sniffing will work.”

What sort of ridiculous statement is that?

Then they wrote this:

“Take Chrome. It worked pretty well right out of the gate because they tested it against a myriad of web sites. Who is going to release a browser that crashes on jQuery sites, for example?”

jQuery misidentifies Chrome as Safari. You lose.

And browser developers do not bend to browser sniffers. They break them (often intentionally.)

Comment by DavidMark — December 11, 2008

jQuery misidentifies Chrome as Safari. You lose.

It detects Webkit, not Safari. Chrome runs on Webkit like Safari.

Seems like you haven’t looked at Prototype at all because you are to fed up with something else and don’t know what good code is when you see it. No reason for offtopic flaming of some framework with no arguments at all.

Comment by Jadet — December 11, 2008

@David
`isHostMethod` is recommended by Michaux in one of his articles (which I linked to from the blog post). He mentions you in acknowledgment section but there’s no mention of `isHostMethod` belonging to your “My Library”. I will certainly put the credit if that’s where it originates from.

`isHostMethod` is currently not used in any tests and I’m aware of consequences for not doing so. This is something I’m planning to change in a near future (although you will probably argue that it should have been built upon from the beginning). If there are any other stupid mistakes on my part, please do tell; I’m certainly far from an expert.

Comment by kangax — December 11, 2008

>>Actually, I remember many scripts failing in Chrome once it came out : )
.
>>jQuery misidentifies Chrome as Safari. You lose.
.
I don’t think I lose. Chrome was fixed to deal with those cases. The other option would be to fix jQuery and get every old jQuery out there upgraded.
.
So I think I win. The browser had to deal with becoming compatible.

Comment by Nosredna — December 11, 2008

@Nosredna, Chrome uses Webkit and that never needed “fixing”, jquery sniffs for Webkit, nobody wins.

Comment by Jadet — December 11, 2008

Maybe I don’t win. But it’s clear that Chrome needed to make itself work on pages with JS libraries. The libraries were not forced to change.

Comment by Nosredna — December 11, 2008

That had to do with bugs in Chrome’s Javascript implementation, not with the Javascript libraries themselves, these are merely Javascript wrappers. Libraries helped finding these bugs in Chrome, I know Prototype had to change some things around to work with early Chrome bugs. So it works both ways but a browser never bends to some library.

Comment by Jadet — December 11, 2008

Changing the Prototype library to fix problems may have happened. But in order to work with web pages using older versions of the library, of course Chrome bent to the library.
.
Google was very clear about how they were doing testing to make sure they worked with the web as it exists.

Comment by Nosredna — December 11, 2008

Sigh, Chrome bent to Javascript as is exists, not to some library.

Comment by Jadet — December 12, 2008

>>Sigh, Chrome bent to Javascript as is exists, not to some library.
.
Why do you say that? Google explicitly said they were making sure that Chrome worked with the web as it exists. That certainly includes very popular libraries used on large sites.

Comment by Nosredna — December 13, 2008

Not trying to keep the thread on-topic, but has anyone else noticed that this is the ultimate documentation about what-is-broken-in-your-browser? A working javascript testsuite telling what works and what not, that can be used at any time?

On the performance front, you could always downgrade to browser sniffing again for really expensive operations like the Safari 2 bug mentioned here (keep the features API, but use browser sniffing inside if it’s killing for performance).

Comment by icoloma — December 15, 2008

Leave a comment

You must be logged in to post a comment.