What are the best tools for accurate Cross-Browser Testing?

May 4th, 2012


One would almost certainly be forgiven for thinking that given the vast array of tools that web developers have at their disposal, there would be one single tool that would allow you to accurately test for all browsers.

Unfortunately this is not the case.

Modern browsers are being updated regularly, which increasingly makes for a more seamless testing experience.  But at the time of writing, us developers and designers still have to cross swords with Internet Explorer and its older versions.  Support for IE6 was dropped at the turn of the year and our main battle now lies with IE7.  Although The Internet Explorer 7 Countdown currently reports that worldwide usage is now around the 4% mark, although different regions report higher figures than others which requires us to support IE7 for just that little bit longer, fingers crossed.

There are numerous tools that are available to test IE7 from simulators and web based solutions through to legacy versions and here I’m going to run through what I’ve used in the past and what I’m currently using now to get the best possible results.

IE Tester

In my personal experience, IE Tester is the most popular tool amongst my old University friends and work colleagues.  I used it religiously when first starting out in web development and thought it bulletproof without looking around for alternatives.

After time, I began to find out about other alternatives which I’ll go over shortly, and I was finding more and more inconsistencies with what IE Tester was rendering.  In short, IE Tester wasn’t really showing what a proper version of the IE7 browser would.  That’s not to mention the crashing every five minutes which required the program to be restarted:

IE Tester Crash

There are other problems which this software has:  CSS filters don’t work in user mode along with conditional statements often failing and the Debug bar was quite frustrating to use compared to something like Firebug.  This leads me on to the next tool I tinkered with, which came from Microsoft itself.

Internet Explorer 9 Browser Modes

IE9 has a feature that allows you to render your application in versions 7+ by pressing F12 on your keyboard and then selecting the version you require:

IE9 Browser Mode

‘This is it’, I thought.  This is the one thing that I can now use and coming from Microsoft, surely it’s reliable to use.

Not quite.

Although the interface and DOM selection tools were smooth along with the Javascript console, there still were inconsistencies with the rendering.  After adjusting something as trivial as a floated list element to fit within its parent container, even though in the browser mode it looked like it fitted,  after updating the CSS file, I found myself scratching my head when I found the list element down on the next line once more.

There were also times that it even failed to load up the DOM for me to inspect:

IE9 Loading Dom

It’s also worth noting that IE9 has a different Javascript engine to the original browsers, meaning that there are differences in experience between it and a properly installed version of IE7.

Eventually, it became clear that the only real way of testing for the older browsers, is testing using older browsers…

Virtual Machines and IE Collection

I’ve come to find that the most reliable testing can only be done on the actual product itself or the closest version rather than most third-party apps.  Operating Systems have come a long way in a short space of time and it can be quite tricky to get an old version of IE running on Windows 7 if there is currently a version of IE9 running on it.  Windows does not allow you to install an older version ontop of a recent version.

The answer is to use a Virtual Machine to run an older Operating System like XP to install the Utilu IE Collection.  Let’s take a look at Virtual Machines to start.

Virtual Machine Choices

Virtual Machines allow us to run other Operating Systems on our machine as guests.  We can allocate as much memory as we like to the installations along with any operating system we wish.  We can then share the files between the ‘guest’ OS and the ‘host’ OS – perfect for testing.  All we need for this is some Virtual Machine software and a disk image of the OS we want to run on it (Windows XP/OSX/Ubuntu etc).

Like most software, there are different alternatives offering the same service, both paid and through Open Source projects.  Paid options include Parallels and VMWare Fusion while options for Open Source software include QEMU and VirtualBox.  The pros and cons of each package is something to discuss another day.  But just to outline my choice, I chose VirtualBox because it’s free, very easy to set up configure, and comes from a big player in Oracle.

Onto the IE collection.  Straight out of the box, it provides:

  • Standalone versions of IE running from 1 – 9 (You choose which versions you install)
  • Accurate rendering
  • Accurate Javascript engines for each version
  • Access to the IE Developer Toolbar
  • Firebug Lite extension on IE7 and 8

Windows XP IE Collection

I did mention that this is the most reliable in my experience, but it is not completely free of its flaws.

Running multiple versions of IE on the same system will produce various runtime issues.  Different configurations will try to override each other which can sometimes produce confusing and eventually misleading results.  One recent example involved me not being able to click on an input box and type in text in IE7 when using my virtual machine.  Once I tested it on another virtual machine with just the one installation of IE, it rendered and processed correctly.

That example outlined another option and route to minimize the risk of the inteferring issues.  There is nothing to stop us running multiple virtual machines which run single versions of each browser.  That is of course down to your resources as you would require a licence for each virtual machine installation along with the memory on your physical machine to run them!

Making up the numbers: Web Based Testing Apps

There are a few web based apps which take static ‘shots’ of your website. A few exmaples are BrowserCam and Adobe’s BrowserLab.

While these sites are useful for static layout testing, they don’t really help with anything else because they don’t allow you to test your sites interactions.  For this reason alone I prefer to stick to the Virtual Machines due to them being a more complete tool.

Conclusion

I hope that my testing workflow has helped shed some light on some of the options that you have available.  It would be great if you could share your thoughts and the tools you use by leaving a comment!

 

Extending WP-Members plugin: hiding private posts from non-logged in users

March 6th, 2012


I’ve been using the excellent WP-Members plugin, to extend the Swansea Community Church website, and have been pleased with its ability to offer all the membership/registration functionality that I need to add a membership section.

However there a couple of elements that I wanted to add to it to focus it for my needs.

  1. Firstly, to set a post as public or private (overriding the default ‘block all’ or ‘allow all’ settings), I needed to add a custom field to that post. This is fine for me as a developer, but as the admin of the site is not a developer, I wanted to make it more user friendly.
  2. Secondly, I want to be able to remove private posts from the loop (and this covers posts, podcasts, and things like the Recent Posts plugin, etc) when a visitor is not logged into the website, but then show everything to the logged-in user.

This blog article is the second of two articles. Find the first here: Extending WP-Members plugin: Add meta box for public/private

Hiding ‘blocked’ posts

The WP-Members plugin marks private posts as ‘blocked’ with a custom field of ‘block’ having the value ’1′ or true. We need a way to stop listing posts with this custom field.

There are a number of different places blocked posts are currently listed:

  • Blog / category pages (the main ‘loop’)
  • Listing widgets, e.g. Recent Posts plugin
  • Other post types, e.g. Podcasts, Events (e.g. when events are added via The Events Calendar plugin, they are stored as an Events post type)

To go through each plugin and rewrite each to no longer include the post meta (custom field) of ‘block’ would be a laborious process, and is likely to not only introduce bugs, but also will be a maintenance nightmare: each time a plugin is updated you’d have to check whether the code is compatible, and modify appropriately, etc.

Thankfully, we can filter the query with a WordPress query filter hook, which will affect every call using a standard query. Note that this will not affect get_posts by standard unfortunately (the ‘suppress_filters’ is turned off by default) and so you may have to do some testing to see which areas of your site are affected.

The ‘posts_where’ filter

There are filters for the different part of the posts query, however we want to limit posts to those ‘where the post doesn’t have the block post meta set’. Therefore we will use the ‘posts_where’ filter, filtering the ‘WHERE’ clause of the SQL query.

  1. add_filter('posts_where', 'hide_private_posts_from_guests');
  2. /**
  3.  * Hide posts (of any post type) from the loop when user not logged in
  4.  */
  5. function hide_private_posts_from_guests($where)
  6. {
  7.     // don't hide from admin
  8.     if( is_admin() ) return $where;
  9.  
  10.     // if user isn't logged in
  11.     if ( !is_user_logged_in() )
  12.     {
  13.       // we will do our filtering here
  14.     }
  15.  
  16.     return $where;
  17. }

In our filter, we call our function ‘hide_private_posts_from_guests’. We first check we’re not in the admin – we don’t want to limit posts from admin users (this is kind of a redundant check because of is_user_logged_in() but it doesn’t hurt to be explicit sometimes). We then only want to filter posts for users who are not logged in, thus only showing all posts (leaving the query as it is) for users who are logged in.

We then return the $where statement (that will be modified shortly) – as this is a filter we always return a value.

How to select posts that don’t have the ‘block’ meta data set

Although WP_Query is great (check out the parameters here), There unfortunately isn’t the ability in the meta queries (see ‘Custom Field Parameters’ in the Codex page above) to query posts that don’t have a meta field – you can query those posts that do have a meta field, but not the other way round.

Therefore we’ll have to get our hands dirty with some SQL. The way to achieve this is to use a subquery. It would be preferable to use a Join but this isn’t as straightforward in this case.

Here’s all our subquery:

  1. SELECT $wpdb->posts.ID
  2. FROM $wpdb->posts
  3. INNER JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
  4. WHERE $wpdb->postmeta.meta_key = 'block'

This SQL query returns a list of post IDs of posts that have a postmeta key of ‘block’ (this requires an INNER JOIN to the postmeta table).

The posts_where filter extends the ‘WHERE’ clause, to select any post IDs not in a list of post IDs that have the ‘block’ key. Our subquery is then returning the second part of this.

Here’s how we extend the WHERE statement to un-include those posts that are returned from our subquery:

  1. global $wpdb;
  2. // subquery to select all posts that are explicitly 'blocked', then make sure we don't
  3. // include those in the main query's results
  4. $where .= " AND ($wpdb->posts.ID NOT IN
  5. (SELECT $wpdb->posts.ID
  6. FROM $wpdb->posts
  7. INNER JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
  8. WHERE $wpdb->postmeta.meta_key = 'block'
  9. )
  10. ) ";

We’re using the NOT IN SQL operator to reduce our list down to the posts we want.

Our total code is as below:

  1. add_filter('posts_where', 'hide_private_posts_from_guests');
  2. /**
  3.  * Hide posts (of any post type) from the loop when user not logged in
  4.  */
  5. function hide_private_posts_from_guests($where)
  6. {
  7.  // don't hide from admin
  8.     if( is_admin() ) return $where;
  9.  
  10.  // if user isn't logged in
  11.  if ( !is_user_logged_in() )
  12.  {
  13.      global $wpdb;
  14.      // subquery to select all posts that are explicitly 'blocked', then make sure we don't
  15.      // include those in the main query's results
  16.      $where .= " AND ($wpdb->posts.ID NOT IN
  17.          (SELECT $wpdb->posts.ID
  18.           FROM $wpdb->posts
  19.           INNER JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
  20.           WHERE $wpdb->postmeta.meta_key = 'block'
  21.          )
  22.         ) ";
  23.     }
  24.  
  25.     return $where;
  26. }

Thoughts

The weakness of this code is that it has to run the post subquery which can return a pretty large results set when you have a lot of posts (so consider the scalability here), however we are limited by the tools that we have. It would be great if the WordPress API included a ‘not having meta key’ meta query.

Can you come up with a better alternative?

Extending WP-Members plugin: Add meta box for public/private

March 5th, 2012


I’ve been using the excellent WP-Members plugin, to extend the Swansea Community Church website, and have been pleased with its ability to offer all the membership/registration functionality that I need to add a membership section.

However there a couple of elements that I wanted to add to it to focus it for my needs.

  1. Firstly, to set a post as public or private (overriding the default ‘block all’ or ‘allow all’ settings), I needed to add a custom field to that post. This is fine for me as a developer, but as the admin of the site is not a developer, I wanted to make it more user friendly.
  2. Secondly, I want to be able to remove private posts from the loop (and this covers posts, podcasts, and things like the Recent Posts plugin, etc) when a visitor is not logged into the website, but then show everything to the logged-in user.

This blog article will address (1), and I’ll focus on (2) in a second post.

Existing Custom Fields

Currently the user has to add the following custom fields to make a post public or private:

  • ‘block’ with a value of true or ’1′ to ensure that the post is blocked from non-logged in users.
  • ‘unblock’ with a value of true or ’1′ to ensure that the post is visible to all users.

If a user does not set one of these values, the visibility will depend on the setting that they have set in the Settings -> WP Members screen, which if you don’t change any settings, defaults to block posts to non-logged in users.

Custom fields on their own (with no UI) have a couple of problems:

  1. It requires the user to remember the field name
  2. The user must remember the potential values for the field
  3. The user has to know how to view a post’s custom fields (as WordPress hides it by default)

I should point out that this is no fault of the plugin author, rather WordPress continues to add functionality and has made it very easy to add a user interface over custom fields.

Add Meta Box

The solution to this is to create a meta box that will set these fields in a more user friendly interface.

We will create a meta box that will allow the user to select one of three states:

  • Default – leave it as the settings
  • Public – force this post to be viewable to all (setting the ‘unblock’ field)
  • Private – force this post to be viewable only to logged in users (setting the ‘block’ field)

A set of radio buttons is the ideal solution for this – allowing users to choose only one option.

First we must hook into the ‘add_meta_boxes’ WordPress action. This fires when meta boxes are to be added to a post screen, and we pass it our function name that will draw the meta boxes.

  1. <?php
  2.  
  3. add_action( 'add_meta_boxes', 'ds_members_addmetabox' );
  4.  
  5. // backwards compatible (before WP 3.0)
  6. // add_action( 'admin_init', 'ds_members_addmetabox', 1 );
  7. /**
  8.  * Adds a box to the main column on the post type edit screens to allow users to select the visibility of their post
  9.  */
  10. function ds_members_addmetabox()
  11. {
  12.     // add the meta box to each post type
  13.     $post_types=get_post_types('','names');
  14.  
  15.     foreach ($post_types as $post_type)
  16.     {
  17.         add_meta_box(
  18.             'ds_members_addblock_unblock_meta',
  19.             'Members',
  20.             'ds_members_addblock_unblock_meta',
  21.             $post_type,
  22.             'side',
  23.             'default'
  24.         );
  25.     }
  26. }
  27. ?>

We are using the add_meta_box function, passing it the id (arbitrary, but I normally set it to be the same as the callback function name), the title (‘Members’), our callback function name, the post type (more on this in a second), its position (on the side), and if it should appear at the top or the bottom (we’re happy with the default here).

We have to tell it which post type we are adding it to. Most examples add it to just ‘post’ and ‘page’, but what if your system is using custom post types (e.g. The Events Calendar uses an Event post type)? We can use the get_post_types() function to list out all the post types. We only care about the names of the post types so we call it with a second parameter of ‘names’ (so we can reduce the database query load).

We loop through the post types and add the meta box to each post type.

The meta box itself

Now we need to implement our meta box callback function. This is the one that outputs the meta box UI itself.

  1. <?php
  2.  
  3. /**
  4.  * Display contents of post visibility meta box
  5.  */
  6. function ds_members_addblock_unblock_meta($post)
  7. {
  8.     $block = get_post_meta($post->ID, 'block', true);    // allows you to block a post if all posts are currently unblocked
  9.     $unblock = get_post_meta($post->ID, 'unblock', true); // allows you to unblock a post if all posts are currently blocked
  10.     $default = !($block || $unblock);    // default = whatever is currently set in the WP Member settings
  11.  
  12. ?>
  13.     <p>Customise the visibility of this article for logged in users.</p>
  14.     <p><input type="radio" value="default" name="members_block_unblock" <?php echo ($default ? 'checked' : ''); ?>/> Default - dependent on your default members settings</p>    
  15.     <p><input type="radio" value="public" name="members_block_unblock" <?php echo ($unblock ? 'checked' : ''); ?>/> Public - visible to all users</p>    
  16.     <p><input type="radio" value="private" name="members_block_unblock" <?php echo ($block ? 'checked' : ''); ?>/> Private - logged in members only</p>    
  17. <?php
  18. }
  19. ?>

Here we’re getting the meta box values. We first get the custom fields ‘block’ and ‘unblock’ using get_post_meta(). We decide if it’s got any of those fields set – if not, we know that the user is using just the ‘default’ setting.

Then we output the radio buttons, and set them to be ‘checked’ if the appropriate value has been set.

Saving the meta box

Now we need to be able to save the settings when the post type is saved. We use the ‘save_post’ action to save our custom fields:

  1. <?php
  2.  
  3. add_action( 'save_post', 'ds_members_save_postmeta' );
  4. /**
  5. * Save the post visibility custom meta
  6. */
  7. function ds_members_save_postmeta($post_id)
  8. {
  9. // verify if this is an auto save routine.
  10. // If it is our form has not been submitted, so we dont want to do anything
  11. if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
  12. return;
  13.  
  14. if (isset($_POST['members_block_unblock']))
  15. {
  16. $block_unblock = $_POST['members_block_unblock'];
  17. switch ($block_unblock)
  18. {
  19. case 'default':
  20. delete_post_meta($post_id, 'block');
  21. delete_post_meta($post_id, 'unblock');
  22. break;
  23. case 'private':
  24. update_post_meta($post_id, 'block', '1');
  25. delete_post_meta($post_id, 'unblock');
  26. break;
  27. case 'public':
  28. delete_post_meta($post_id, 'block');
  29. update_post_meta($post_id, 'unblock', '1');
  30. break;
  31. }
  32. }
  33. }
  34.  
  35. ?>

First we do some default checking (you can also check a member’s capability and access level here, but I’ve left this out for clarity’s sake. See the add_meta_box example for more details).

Then we check whether our radio button field has been set in the $_POST array, and depending on the value that was set, we use update_post_meta() to set the value, and delete_post_meta() to delete the value that we do not want set (in case the user has changed their mind).

Finished!

And that’s it, you’ve now got a nice user interface that less technical people can use to administer your membership-based website, allowing them to set posts to be public or private without knowing the details of how to set custom fields.

Let me know if this was useful to you, or if you have any comments. Check back in soon for the second part addressing the visibility of posts.

Setting the meta description in the All in One SEO plugin

January 10th, 2012


A little tip to save you the time it took me to work out what was going on with the All in One SEO plugin for WordPress, and why a site I recently converted from static to WordPress lost its Google ranking for a while. Each page had an optimised title and meta description, yet when I googled the site, the meta description wasn’t showing up in Google.

With the All in One SEO plugin, you are able to set an optimised page title, and a meta description. This is done from the Edit page screen for the pages in question. I’d set this information for the Home page (which was a static page), so why wasn’t it shown up?

It turns out that the All in One SEO plugin doesn’t use the title and description set on the ‘Home’ page’s Edit page screen, even if it’s been set. Instead it looks at the Settings -> All in One SEO page instead, which has two fields: ‘Home Title’ and ‘Home Description’. I would argue that this is not an obvious place to store this information, and that the plugin should be implemented to look at the Home page’s ‘Edit page screen’ details, if it’s not set here.

Mobile Applications vs Mobile websites

December 5th, 2011


 

A common request from clients is for a mobile application to partner their website (“I’d like an iPhone/iPad app”). This is not a bad request in itself, but I often will discuss with them their reasons for wanting an app, so that they are not spending unnecessary budget on development. Quite often, a mobile website will do the same job or even a better job, than an application.

Strengths and Weaknesses

It’s important to consider the strengths of a mobile application versus a mobile website:

  • A mobile app can access all/most hardware capabilities (e.g. camera, geo location, offline data storage, compass, standard interface elements like tabs and list views). A mobile app can be hardware optimised.
  • A mobile website can access some but not all hardware capabilities (e.g. geo location, offline data storage). A mobile website is limited to the browser’s capabilities and Javascript engine speed, but there is a lot that a browser can do.

 

  • A mobile app can generate income via the App Store or Android Marketplace. This means that the developer doesn’t have to add a sales mechanism (e.g. merchant banking, PayPal, etc).
  • A mobile website can generate income only through online payment engines (e.g. PayPal, etc).

 

  • A mobile app (on iPhone/iPad) can only sell subscriptions to content through the App Store, giving 30% to Apple. Apple owns the relationship with the consumer, rather than the client.
  • A mobile website can completely own the relationship with the client, which can be leveraged for other sales opportunities.

 

  • A mobile app can be launched via a URL, but managing this URL cross-device is challenging. This is an issue when sending emails with links to content.
  • A mobile website can be integrated with an email strategy or other linking. A mobile website URL is cross-browser compatible.
  • A mobile app has to be found via the App Store / Android Marketplace – searching for and getting found by users is haphazard to say the least. A mobile app launch should be accompanied by multiple marketing strategies including the web, to point users to the App Store / Android Marketplace.
  • A mobile website can be found by Google, and standard web marketing strategies and SEO can be used to bring users to your website. In addition, existing users of your website do not have to download a separate application; they can instead be switched automatically to your mobile website and brought online to the mobile experience.

Case Study: The Financial Times

A good example of an organisation choosing a mobile website over a mobile application is the Financial Times. They chose to remove all their mobile applications from the App Store  / Android MarketPlace, and developed a feature rich mobile website. See the following article: http://www.mobile-ent.biz/news/read/ft-s-html5-app-has-1m-users/016218. Some of the standout figures include:

  • 20% of all online page views are via the mobile website
  • 15% of all new digital subscriptions come via the mobile website.

The lesson is that we should consider the requirements of the mobile experience for the user, and then choose a platform (website or application) following this. Don’t assume that an application is always the solution.

Why Responsive Design Actually Begins on the Server

December 1st, 2011


There is a very interesting presentation at http://www.slideshare.net/yiibu/adaptation-why-responsive-design-actually-begins-on-the-server . It covers the challenges in responsive mobile site creation, and proposes a hybrid solution of device profiles to solve it.

The first half of the presentation is worth showing anyone who does not understand the challenge of developing a mobile website that works well on multiple mobile devices, not just on the latest and greatest iPhone / Samsung / HTC.

It’s strongest point is that many people (especially in this current financial climate) will not have the latest leading edge device. In fact, your cutting edge, state of the art device from 2 years ago (read iPhone 3/3G) is now old and destined for the mobile device rubbish heap. However many people will not automatically upgrade, but will keep them, and thus there is a great proliferation of devices which don’t support the latest HTML5, slower Javascript, etc.

Added to this is that the word ‘smartphone’ retains a nebulous definition, and in fact today’s ‘cheap’ devices contain most of the features that a smartphone has (e.g. touch screen, browser), however their ability to serve the web may not be as perfect as Apple’s Mobile Safari.

This is the reason that content adaptation has had a number of solutions, via examples such responsive design, server-side detection and adaption, etc.

The solution proposed in this system is not a simple solution. It proposes an aggregation of device information (e.g. from DeviceAtlas) on top of a default device profile, stored in cookies, sent via Javascript to the server to analyse. To implement it for a client, I for one would hope to see a library to help achieve this without the larger development cost, so I will be watching closely.

There are also some interesting suggestions at the end of the presentation about some potential options for the future, e.g. changing the <img> from having one source file to having multiple source files (similar to the way the <video> tag is currently done). I would be interested in this option, however the reality is that the HTML change process is long and tortuous and thus I won’t be holding my breath.


Switch to mobile version