<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">

  <title>Mogoblog</title>
  
  <link href="http://mogotest.com/blog" />
  <updated>2011-12-05T13:24:49-05:00</updated>
  <id>http://mogotest.com/</id>
  <author>
    <name>Mogoterra</name>
    <email>team@mogotest.com</email>
  </author>
  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/Mogoblog" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="mogoblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title>Presenting Web Consistency Testing</title>
    <link href="http://mogotest.com/2011/11/30/presenting-web-consistency-testing" />
    <updated>2011-11-30T00:00:00-05:00</updated>
    <id>http://mogotest.com/2011/11/30/presenting-web-consistency-testing</id>
    <content type="html">&lt;p&gt;Before I started working on Mogotest I spent a lot of time thinking about the current state of Web development and testing and how we might be able to improve upon it.  I was frustrated with the seeming lack of progress being made because it appeared the entire industry was stuck on some local maxima.  Having a machine learning and HCI background, I tried to think of Web testing in terms of what matters to a visitor and how a computer could automate that process.  This initial work formed the basis for what would evolve into Web Consistency Testing and eventually started my career at Mogotest trying to advance these concepts.&lt;/p&gt;

&lt;p&gt;Web Consistency Testing (WCT) is a new approach towards testing Web pages.  It tests how a page is rendered &amp;mdash; how it's viewed by those visiting your site or using your web app.  This is arguably one of the most important aspects of a site.  Study after study has shown how a poor user experience is tightly correlated with loss in revenue.  More recently startups have been relying on the design of their sites as a way to differentiate themselves from the pack.  The look and feel of a site or app is what sets each of us apart, but it's also one of the hardest things to implement correctly and maintain (regressions are all too common).  On top of all that, we traditionally haven't tested this core aspect of our sites &amp;amp; apps because there hasn't been a good way to automate it and testing manually is laborious, expensive, and error-prone.&lt;/p&gt;

&lt;p&gt;I recently was fortunate enough to present &lt;a href="http://webconsistencytesting.com/"&gt;Web Consistency Testing&lt;/a&gt; at Google's Test Automation Conference.  The talk goes into the details of how it works and how to build a WCT system, with Mogotest serving as the vessel through which many of these concepts have been validated.  I also set up a site at &lt;a href="http://webconsistencytesting.com/"&gt;http://webconsistencytesting.com&lt;/a&gt; for the community to experiment, learn, and further develop the principles.  We had always planned on opening up the work we do at Mogotest and we have opensourced a lot of code, but this is the first time we've really detailed how everything works.  We're happy to be the go-to company for Web Consistency Testing, but competition is good, and more than anything else we'd like to see the industry test smarter and spend more time making the Web a better place for all.  I hope you enjoy.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Posting a file through the Mogotest API</title>
    <link href="http://mogotest.com/2011/11/17/posting-a-file-through-the-mogotest-api" />
    <updated>2011-11-17T00:00:00-05:00</updated>
    <id>http://mogotest.com/2011/11/17/posting-a-file-through-the-mogotest-api</id>
    <content type="html">&lt;p&gt;We recently rolled out a big enhancement to &lt;a href="https://mogotest.com/docs/display/API/Attaching+Documents+to+a+Prepared+Test+Run"&gt;our prepared test run API&lt;/a&gt;.  This API allows you to create a test run without actually starting it, so you can customize the run by adding your own URLs.  Previously, the URLs needed to be accessible, either publicly our through our &lt;a href="https://mogotest.com/docs/display/HOWTO/Test+a+Site+on+a+Private+Network"&gt;tunnel tool&lt;/a&gt;.  Sometimes, however, the page you want to test is only accessible after you've conditioned it in some way.  Perhaps you use Selenium and you want to submit a form then test the page in Mogotest.  Well, now you can do just that.&lt;/p&gt;

&lt;p&gt;When you add a URL to the test run you can now optionally send a &lt;code&gt;file&lt;/code&gt; value along with it.  You have two options here: POST to our API using a multi-part form just as you would when uploading a file on a web site; or, just set the &lt;code&gt;file&lt;/code&gt; value to a string representation of the file you want to upload (binary files must be base64-encoded).  When you start the test run, we'll reassemble the document and any linked resources you've posted on an internal web server that we'll test against.  That way we can test against the same state you had your site in at the time you uploaded the files to us.  You can also mix-and-match between testing uploaded files and others that you just want to retrieve directly from your Web server.&lt;/p&gt;

&lt;p&gt;This is a great way to integrate Mogotest with your existing functional testing suite.  Let us know what you think!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Introducing Firefox 5 and Firefox 6 Support</title>
    <link href="http://mogotest.com/2011/08/17/introducing-firefox5-and-firefox6-support" />
    <updated>2011-08-17T00:00:00-04:00</updated>
    <id>http://mogotest.com/2011/08/17/introducing-firefox5-and-firefox6-support</id>
    <content type="html">&lt;p&gt;We're happy to introduce Firefox 5 and Firefox 6 into the suite of browsers tested by Mogotest.  With these additions we now support Firefox 3.6, 4, 5, and 6, accounting for nearly all modern Firefox traffic.  While we're a bit late to the game with Firefox 5, we've fixed that for Firefox 6, launching support for the browser less than 24 hours after its public release.  We're working hard to ensure we're able to do the same thing for the Firefox 7 release a few months down the road.&lt;/p&gt;

&lt;p&gt;We added these two browsers to all existing sites being tested, so the next time you run a test you should see the results.  As always, please &lt;a href="mailto:support@mogotest.com"&gt;share any feedback&lt;/a&gt; you have or let us know if you otherwise have any questions, comments, or concerns.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Filtering Mogotest Traffic in Google Analytics</title>
    <link href="http://mogotest.com/2011/08/15/filtering-mogotest-traffic-in-google-analytics" />
    <updated>2011-08-15T00:00:00-04:00</updated>
    <id>http://mogotest.com/2011/08/15/filtering-mogotest-traffic-in-google-analytics</id>
    <content type="html">&lt;p&gt;One of the questions we've been asked more frequently is: how can we filter Mogotest traffic in our analytics tool?  While our spider uses a customer user agent (mogobot) that's easy to filter on, the test browsers have been considerably trickier.  We use actual browsers to run our tests and we can't change the user agent string, since that would break tests for the large number of sites still doing user agent sniffing.  Additionally, we use EC2 to scale up our service, so our block of IPs can change at any given time, making traditional IP filtering all but useless.&lt;/p&gt;

&lt;p&gt;Well, I'm happy to say that after some heavy internal testing we now finally have a good answer to the problem.  All outgoing traffic from the Mogotest browsers is filtered through a pool of proxy servers with static IP addresses so we can employ IP or hostname-based filtering.  We wrote up a howto for &lt;a href="https://mogotest.com/docs/display/HOWTO/Filter+Mogotest+Traffic+in+Google+Analytics"&gt;filtering Mogotest traffic in Google Analytics&lt;/a&gt; specifically, but the approach is general enough to apply to all analytics packages.  This was a rather large architecture change for us that we wanted to ensure wouldn't break test runs, so we very much appreciate your patience as we rolled it out.&lt;/p&gt;

&lt;p&gt;A tangential benefit is we can now internally cache resources your site marks as cacheable.  This should yield faster tests in general, but for those of you that were testing on weaker hardware that couldn't handle all the traffic Mogotest would send your way at once, this will avoid the "thundering herd" problem you were experiencing that was potentially knocking your site offline.  The gains overall should be quite substantial.  Try running a test and &lt;a href="mailto:team@mogotest.com"&gt;let us know what you think&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Give Us A Call!</title>
    <link href="http://mogotest.com/2011/07/11/new-phone-number" />
    <updated>2011-07-11T00:00:00-04:00</updated>
    <id>http://mogotest.com/2011/07/11/new-phone-number</id>
    <content type="html">&lt;p&gt;Want to talk to us?  Give us a call!  We'd like to introduce our new phone number: 1-888-MOGO-TST (toll free within the US).  Feel free to call with any questions, technical issues, or feedback.  As always, we're still available by &lt;a href="mailto:support@mogotest.com"&gt;email&lt;/a&gt; and &lt;a href="#" onclick="return SnapABug.startLink();"&gt;chat&lt;/a&gt;.  Whatever form of communication you prefer we'd love to hear from you!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Check Out Our New Look!</title>
    <link href="http://mogotest.com/2011/06/27/site-redesign" />
    <updated>2011-06-27T00:00:00-04:00</updated>
    <id>http://mogotest.com/2011/06/27/site-redesign</id>
    <content type="html">&lt;p&gt;As you may have noticed by now, our site is looking a little different these days.  We've refreshed our look and have tried to make things easier to find.  What do you think?  The good news is that this isn't the only improvement you'll see.  Over the next couple months we'll be rolling out several more to enhance the user experience with Mogotest.  Stay tuned for future developments and thanks for all the feedback!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Introducing Internet Explorer 9 and Firefox 4 Support</title>
    <link href="http://mogotest.com/2011/05/09/introducing-ie9-and-firefox4-support" />
    <updated>2011-05-09T00:00:00-04:00</updated>
    <id>http://mogotest.com/2011/05/09/introducing-ie9-and-firefox4-support</id>
    <content type="html">&lt;p&gt;We're happy to introduce Internet Explorer 9 and Firefox 4 into the suite of browsers tested by Mogotest.  Both browsers are fully supported, including screenshots (both browser and full-canvas) and browser compatibility reporting.  We've been internally testing support for these browsers for a little while now and have been itching to get them released for general consumption.  While we have been hammering on them, since these two browsers haven't been as widely tested on Mogotest as those that came before them, there may very well be some lingering issues related to browser compatibility reporting.  If you find any, please &lt;a href="mailto:support@mogotest.com"&gt;let us know&lt;/a&gt; and we'll be sure to look into them.&lt;/p&gt;

&lt;p&gt;Support for the new browsers has been rolled out to all existing customers and is enabled by default for new ones, so you don't need to do anything to configure them.  The next time you run a test you'll see both browsers in your test results page.  Enjoy!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>New Pricing Plans and Chat Support</title>
    <link href="http://mogotest.com/2011/03/01/new-pricing-plans-and-chat-support" />
    <updated>2011-03-01T00:00:00-05:00</updated>
    <id>http://mogotest.com/2011/03/01/new-pricing-plans-and-chat-support</id>
    <content type="html">&lt;p&gt;Our &lt;a href="http://mogotest.com/pricing"&gt;new pricing plans&lt;/a&gt; have finally arrived!  After a lot of valuable feedback we have created five pricing plans that range in price and features.  We have tried our best to meet everybody’s needs and budgets while maintaining the quality of the service and support we can offer.  Here’s an overview of the new plans:&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Personal&lt;/strong&gt; plan is a very lean version of our Mogotest service.  It offers full canvas screenshots and HTML &amp;amp; CSS validation.  You also get access to our API.  This plan is ideal for those developers that just want to visually inspect their site in different browsers.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Freelancer&lt;/strong&gt; plan adds some very cool features in addition to those found in the Personal plan.  A Freelancer plans give you the ability to test authenticated pages, automate site configuration for nested pages through spidering, schedule test runs, and most importantly, access to our browser compatibility report, which automatically detects rendering issues in your pages across browsers.&lt;/p&gt;

&lt;p&gt;Our &lt;strong&gt;Team&lt;/strong&gt; plan focuses on the team aspect of Web development.  It features everything in the Freelancer plan, but also includes an unlimited number of user accounts.  This gives your whole development team access to the testing resources they need to make your site compatible across browsers.  The plan also features test groups and VPN/Firewall support which allow you to logically group related URLs together and access sites that are not publicly accessible, respectively.&lt;/p&gt;

&lt;p&gt;Our &lt;strong&gt;Agency&lt;/strong&gt; plan offers all of the features of the previous plans plus custom reporting.  These reports will allow you to export your test data into CSV, XML, and JSON formats so you can manage your data the way you want.  This is intended for high volume testing, where a Web UI would be too cumbersome.&lt;/p&gt;

&lt;p&gt;And lastly, there is our &lt;strong&gt;Enterprise&lt;/strong&gt; plan.  This is the ultimate plan, which offers you every feature we have to offer with no limits.&lt;/p&gt;

&lt;p&gt;You can visit our &lt;a href="http://mogotest.com/pricing"&gt;pricing page&lt;/a&gt; to learn more about the pricing and features available for each of the plans.&lt;/p&gt;

&lt;p&gt;Also if you haven’t noticed, we are now available for chat to answer any of your questions.  When visiting mogotest.com all you have to do is click on the green help button on the left-hand side of your browser window and you’ll be given the option to chat or email.&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/static/new-pricing-and-chat/chat_button.png" /&gt;&lt;/p&gt;

&lt;p&gt;Of course we can only chat with you if we're at our computers, but we try to be available as much as possible.  If we’re not available for chat or if you'd rather just send email, please write your question, comment, or suggestion in the email section of the chat window and we'll get back to you as soon as possible.  No question is too small and we like to talk with our customers, so don’t hesitate to hop on and let us know how we’re doing or how we can help you.  We’d also be more than happy to answer any of your questions about our new pricing plans.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Invalid Charges for AppSumo Promotion</title>
    <link href="http://mogotest.com/2011/01/31/invalid-charges-for-appsumo-promotion" />
    <updated>2011-01-31T00:00:00-05:00</updated>
    <id>http://mogotest.com/2011/01/31/invalid-charges-for-appsumo-promotion</id>
    <content type="html">&lt;p&gt;About four months ago we ran a promotion for Mogotest through &lt;a href="http://appsumo.com/"&gt;AppSumo&lt;/a&gt;, a great site for getting deals on modern Web apps.  This was the first time we ran a promotion through a third-party site and it was a great experience for us overall.  However, we did run into various hiccups, most notably with our billing provider.  Now that we’ve done one promotion and ironed out most of the problems related to it we are looking forward to doing more in the future.  However, we do regret that some AppSumo customers did experience difficulties, which we tried to fix as quickly as possible.&lt;/p&gt;

&lt;p&gt;Most recently you may have noticed we experienced a problem with our billing system.  This was a problem that we spent considerable time trying to avoid, but due to our third-party billing provider we were unable to avoid it.  Basically, every AppSumo signup was set up to auto-convert into our paid product.  Initially this was the only option available to us, even though we weren't keen on it (who wants to remember to cancel something in four months?).  Over the course of the four month promotion, however, we were able to suspend accounts rather than convert them into paying customers.  We set this up with our billing system, they told us that no one would be charged, I emailed all of you telling you such, and sure enough, many of you got charged anyway.&lt;/p&gt;

&lt;p&gt;As soon as we caught the issue, we issued refunds to any of you that were affected and cancelled your accounts (so we no longer have your billing details).  The refunds occurred fast enough such that you should have never been charged, although there may have been a hold on your account due to the charge authorization.  The authorizations should drop off after a few days.  If not, please feel free to contact &lt;a href="mailto:kevin@mogotest.com"&gt;me directly&lt;/a&gt; and I'll get it squared away.&lt;/p&gt;

&lt;p&gt;We have been unhappy with our current billing provider for a few months, but we were hesitant to change to a new provider for fears of unforeseen billing problems.  Ultimately, this latest incident has pushed us to the edge and we will begin to change billing providers as soon as we have found a new one that meets our needs.  Again, I apologize for any inconveniences you may have experienced with inadvertent billing or any other billing issues that may have occurred.  If you have any questions or concerns about your billing do not hesitate to contact us.  We hope all of our AppSumo customers enjoyed their four month subscription to Mogotest and we wish you all the best with your Web development work.&lt;/p&gt;

&lt;p&gt;As for all of our continued customers, you may be wondering how this billing provider change may affect you.  We will keep you updated as we make the change and we will let you know of any actions you may have to take.  Until then, happy testing!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Mogotest: Automated Cross Browser Render Issue Detection</title>
    <link href="http://mogotest.com/2010/08/18/automated-cross-browser-render-issue-detection" />
    <updated>2010-08-18T00:00:00-04:00</updated>
    <id>http://mogotest.com/2010/08/18/automated-cross-browser-render-issue-detection</id>
    <content type="html">&lt;p&gt;We've been rather busy since we launched paid plans for Mogotest just three weeks ago.  We're very pleased to announce our new automated issue detection feature for discovering cross browser rendering inconsistencies.  Whereas we've always spidered your site and presented you with a set of screenshots for each URL, this feature will compare the rendering output from two browsers and detect any major rendering inconsistencies, saving you the time hassle of having to manually compare screenshots by inspection.  The results for your entire site are available in a concise report and the comparison views have been enhanced to highlight the rendering differences.&lt;/p&gt;

&lt;p&gt;Some screenshots should help illustrate things:&lt;/p&gt;

&lt;div class="figure"&gt;
  &lt;img src="/images/static/auto-issue-detection/overview.png" /&gt;

  Figure 1: Overview of browser render results.
&lt;/div&gt;


&lt;p&gt;Fig. 1 shows the new overview report when a test job is completed.  You have a matrix of results indicating your site's browser compatibility at the render level relative to a reference browser.  The reference browser is the one used during primary development and should represent the canonical rendering of the site.  Here we're using Firefox 3.5 on Linux as our reference browser.  In this case, when testing the techstars.org site, we see that the /iphone-app/ path is particularly problematic across most browsers and that Internet Explorer 6 has render issues across most paths.&lt;/p&gt;

&lt;p&gt;If you click on a cell, you're taken to a diff view of that path showing differences in that browser relative to the reference browser.  Fig. 2 illustrates a rendering issue with Chrome 5 on Windows on the /iphone-app/ path.&lt;/p&gt;

&lt;div class="figure"&gt;
  &lt;img src="/images/static/auto-issue-detection/error-diff.png" /&gt;

  Figure 2: Sample error diff between Firefox 3.5 (Linux) and Chrome 5 (Windows).
&lt;/div&gt;


&lt;p&gt;Below the screenshots you can see the list of render issues detected.  When you select an error it highlights the element in both the reference and comparison browser views, adding an overlay with the upper-left-hand and lower-right-hand coordinates to aide in debugging.  If you decide that the render issue is acceptable, you can simply choose to ignore the issue and you won't be bothered with it again.&lt;/p&gt;

&lt;p&gt;The improved reporting has cascaded down to our notification emails, too.  Whereas previously you would have to click through to our site to see if there were any rendering issues, we now report problems by browser in the notification email (see Fig. 3).  Additionally, we indicate the change in errors from the previous test run to help you better determine if it's something you need to look into immediately or if it's a problem that can be deferred.&lt;/p&gt;

&lt;div class="figure"&gt;
  &lt;img src="/images/static/auto-issue-detection/email.png" /&gt;

  Figure 3: Enhanced email reporting.
&lt;/div&gt;


&lt;p&gt;The new automated issue detection feature is now available for all paying accounts at no additional cost.  If you'd like to see it in action, try running a &lt;a href="https://mogotest.com/"&gt;free page test&lt;/a&gt;.  And since automated issue detection is something that could always be improved, please report any issues you run into and we'll do our best to handle them better.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Mogotest Public Beta</title>
    <link href="http://mogotest.com/2010/07/19/mogotest-public-beta" />
    <updated>2010-07-19T00:00:00-04:00</updated>
    <id>http://mogotest.com/2010/07/19/mogotest-public-beta</id>
    <content type="html">&lt;p&gt;Mogotest is now in public beta.  This means anyone can now try out a limited version of the service for free.  It's as simple as entering a website address into the free page test box &lt;a href="http://mogotest.com"&gt;on our homepage&lt;/a&gt;.  While these tests won't showcase absolutely everything Mogotest has to offer, it's a great way to run a quick test and try out the service without having to go through the hassle of creating a user account. We hope you like it!&lt;/p&gt;

&lt;p&gt;Now that we're in beta, we'll be doing a bit more spit &amp;amp; polish work and then will begin charging.  We'd like to thank all of you that have contributed to the success of our alpha and now beta programs.  It's been a great five months and Mogotest has evolved considerably with your feedback. Most recently, we've added new features like Chrome browser support and a new "Problems" tab for site-level test run notices, while also improving spidering, authentication handling, and general service responsiveness. We simply wouldn't have been able to do this without your help.&lt;/p&gt;

&lt;p&gt;So how much will it cost? Our individual user plans will be &lt;em&gt;$45 / month&lt;/em&gt;. We'll start charging on &lt;em&gt;July 28, 2010&lt;/em&gt;.  If you don't wish to upgrade to a paid plan at this time, don't worry; you'll still have read-only access to all your existing test run data.  If at any point you decide you do want to upgrade you'll instantly regain the ability to perform test runs, add sites, and modify your test groups.&lt;/p&gt;

&lt;p&gt;As always, please let us know if you have any questions or concerns about our switch to paid plans.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>How to Perform Basic Authentication in Selenium</title>
    <link href="http://mogotest.com/2010/06/23/how-to-perform-basic-auth-in-selenium" />
    <updated>2010-06-23T00:00:00-04:00</updated>
    <id>http://mogotest.com/2010/06/23/how-to-perform-basic-auth-in-selenium</id>
    <content type="html">&lt;p&gt;Performing basic authentication in Selenium 1.x may seem impossible at first glance.  Selenium 1.x drives the browser via JavaScript, but is unable to do anything when the basic authentication dialog pops up.  One way to get around this is to embed the user credentials in the URL.  Traditionally this has worked well, but newer browsers have disabled that functionality due to the security risks inherently involved.  Fortunately, there is another way: send over the authentication credentials in the request header.&lt;/p&gt;

&lt;h2&gt;Selenium as a Proxy Server&lt;/h2&gt;

&lt;p&gt;In order to customize the request headers in Selenium you must be using it as a proxy server.  Unless you use the &lt;code&gt;-avoidProxy&lt;/code&gt; argument when you start up the Selenium server, it will serve as a proxy server bound to localhost (i.e., it is not an open proxy).  You also must use a browser launcher that configures the browser to use the Selenium server as an HTTP proxy.  I discuss this in more depth in my article on &lt;a href="http://mogotest.com/blog/2010/04/13/how-to-accept-self-signed-ssl-certificates-in-selenium"&gt;how to accept self-signed SSL certificates in Selenium&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is a best practice to only perform basic authentication over HTTPS if you're accessing publicly accessible pages.  If all your work is on an internal network and it's a trusted environment, basic authentication over HTTP may be acceptable.  Just realize that basic authentication is plain text and easily sniffable.  If you're connecting to a server with a self-signed certificate you may want to read the aforementioned article on how to do so with Selenium.&lt;/p&gt;

&lt;h2&gt;Basic Authentication with Selenium&lt;/h2&gt;

&lt;p&gt;It probably seems obvious, but you really need to make sure your credentials work.  If they don't, the browser is going to pop up a basic authentication dialog and your Selenium browser session is going to be effectively locked-up.  An example of how to do so in Ruby can be seen in Example 1.&lt;/p&gt;

&lt;pre class='brush: ruby;'&gt;
require 'rubygems'
require 'net/http'

# Check credentials via SSL.
http = Net::HTTP.new('www.example.com', 443)
http.use_ssl = true

# Make the request with the basic authentication credentials.
req = Net::HTTP::Get.new('/')
req.basic_auth('my_user', 'my_password')
response = http.request(req)

# 401 is the HTTP Unauthorized status code.
if response.code == 401
  puts "Basic authentication failed"
  exit(-1)
else
  log_in_with_selenium()
end  
&lt;/pre&gt;


&lt;div class='caption'&gt;Example 1: Ensuring your basic authentication credentials work (in Ruby).&lt;/div&gt;


&lt;p&gt;Once you've verified that your basic authentication credentials do in fact work, you can proceed to add the credentials to your Selenium request.  You do so by adding the "Authorization" header with a value of "Basic " followed by the base 64 encoded "username:password" pair.  The browser will cache this value for all requests within the same session, so you only need to authenticate on the first request.  Example 2 shows how this looks in Ruby using the selenium-client gem.&lt;/p&gt;

&lt;pre class='brush: ruby;'&gt;
require 'rubygems'
require 'base64'
require 'selenium/client'

# Note that the start URL is not on the domain that we need to authorize for.
# If you set the start URL there, you may see the authorization dialog before
# you're able to modify the request.
Selenium::Client::Driver.new \
        :host =&gt; 'localhost',
        :port =&gt; 4444,
        :browser =&gt; '*googlechrome',
        :url =&gt; 'http://localhost:4444',
        :timeout_in_seconds =&gt; 180,
        :highlight_located_element =&gt; false

# Add in the basic authentication header.
encoded = Base64.encode64("#{my_username}:#{my_password}").strip
browser.remote_control_command('addCustomRequestHeader',
                              ['Authorization', "Basic #{encoded}"])

# Request the page, fully authorized.
browser.open('http://www.example.com/')
&lt;/pre&gt;


&lt;div class='caption'&gt;Example 2: Adding basic authentication credentials to Selenium request (in Ruby).&lt;/div&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Since basic authentication credentials can be supplied as an HTTP request header, you can perform basic authentication with Selenium with a little bit of work.  You need to use the Selenium server as a proxy for your browser requests, configure acceptance of self-signed SSL certificates if appropriate, and verify that the credentials work before issuing your request.  Once you do so, you'll be able to test sites without worrying about the browser locking up on the authentication dialog.  Note that this article only addresses basic authentication (the most popular of the HTTP authentication methods).  Digest authentication is a completely different beast and the method laid out in this article will not work for it.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Google Analytics Integration with OAuth</title>
    <link href="http://mogotest.com/2010/05/27/google-analytics-integration-oauth" />
    <updated>2010-05-27T00:00:00-04:00</updated>
    <id>http://mogotest.com/2010/05/27/google-analytics-integration-oauth</id>
    <content type="html">&lt;p&gt;One of the new features we've been working on behind the scenes at Mogotest is
a &lt;a href="http://google.com/analytics"&gt;Google Analytics&lt;/a&gt; (GA) integration.
By integrating with the Web's most popular analytics service, we can help
users see how specific browser rendering problems are affecting their bounce
rates, conversions, and traffic funnels. The sort of stuff you'd like to know
about as a site owner, right? Unsurprisingly, we also use GA ourselves to
monitor our own traffic metrics and have some automated reports that help us
measure our day to day progress.&lt;/p&gt;

&lt;p&gt;In late 2008, Google began moving away from their own AuthSub authorization
system and started offering
&lt;a href="http://code.google.com/apis/gdata/articles/oauth.html"&gt;access to all
their Data APIs via OAuth&lt;/a&gt;. That's A Good Thing&amp;trade;. But since there
doesn't seem to be a wealth of information on the 'net regarding the GA
integration process, I figured it might be worthwhile to document how we
integrated it with a Rails-based application and share it with the community.
The &lt;a href="http://oauth.rubyforge.org/"&gt;OAuth Ruby Gem&lt;/a&gt; makes most of
this process very simple, but there are a few tricky bits that might trip you
up if you haven't worked with OAuth and the Google APIs before.&lt;/p&gt;

&lt;p&gt;The first thing you need to do whenever you're tying into a system using OAuth
is obtain the consumer token and secret from the provider. In this case, the
provider is Google and we can retrieve this information by visiting &lt;a
href="https://www.google.com/accounts/ManageDomains"&gt;Google's Domain
Management Page&lt;/a&gt;. Unfortunately, this URL isn't the easiest to find. I
probably never would have found it if it wasn't for &lt;a
href="http://everburning.com/news/google-analytics-oauth-and-ruby-oh-my/"&gt;Dan
Sinclair's earlier GA + OAuth tutorial&lt;/a&gt;. Here's what it looks like:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/static/google-analytics-integration/google-domain-manager.png" alt="Google Domain Management Page"/&gt;&lt;/p&gt;

&lt;p&gt;Anyway, once you're on the Domain Manager page, add the domain for your
application (the address from which authorization requests will originate).
You'll need to verify ownership by either adding a meta tag to your website,
adding a new page, or modifying a DNS record. Once you've done that Google
will give you the OAuth consumer key and consumer secret you need for the
next steps.&lt;/p&gt;

&lt;p&gt;NOTE: this verification requirement can be painful if you don't have anything
in production yet or need a separate set of credentials for testing or
development. I'd suggest pointing DNS for some URL like test.yourdomain.com
to a staging server to get it up and running and then changing it
post-verification so you have at least two sets of OAuth credentials for the
separate environments.&lt;/p&gt;

&lt;p&gt;To authorize access to a specific GA account (like one belonging to one of our
users), you need an &lt;strong&gt;access token&lt;/strong&gt;. To get an access token, you
first need to create a &lt;strong&gt;request token&lt;/strong&gt;. The workflow for
getting a request token using the OAuth gem involves creating a new
&lt;code&gt;Consumer&lt;/code&gt; object, passing in the consumer key and consumer secret, along with
a few other options, and then calling the &lt;code&gt;get_request_token&lt;/code&gt; method. For
convenience, I've wrapped up the process of requesting a new Consumer into a
library method, since we'll need to do it a couple times. Make sure that the
token paths specified are exactly what is shown below in order for this to
work with Google:&lt;/p&gt;

&lt;pre class='brush: ruby;'&gt;
class GoogleAuth
  def self.consumer
    OAuth::Consumer.new(oauth_consumer_key, oauth_consumer_secret, {
                        :site               =&gt; 'https://www.google.com',
                        :request_token_path =&gt; '/accounts/OAuthGetRequestToken',
                        :access_token_path  =&gt; '/accounts/OAuthGetAccessToken',
                        :authorize_path     =&gt; '/accounts/OAuthAuthorizeToken' })
  end
end
&lt;/pre&gt;


&lt;p&gt;Our call to &lt;code&gt;get_request_token&lt;/code&gt; is going to get made inside the &lt;code&gt;new&lt;/code&gt; action
of our &lt;code&gt;AuthorizationsController&lt;/code&gt;. We'll retrieve the request token,
specifying a callback and a scope. The  &lt;strong&gt;callback&lt;/strong&gt; is the URL
that the user will be directed to after authorizing with Google. The
&lt;strong&gt;scope&lt;/strong&gt; is used to specify the Google service that the user is
authorizing us to access. Google provides
&lt;a href="http://code.google.com/apis/gdata/faq.html#AuthScopes"&gt;many
different API services&lt;/a&gt; in addition to analytics -- Calendar, Documents,
YouTube, etc -- but we want to scope to the Analytics API here. We set the
token and secret in the user session because we'll need them later when the
user returns to the site. Finally, we get the authorization URL from the
request token and redirect the user to it. Note that we also encode
instructions to return to our callback URL after successful authorization.&lt;/p&gt;

&lt;pre class='brush: ruby;'&gt;
def new
  @request_token = GoogleAuth.consumer.get_request_token({ :oauth_callback =&gt; callback_account_authorizations_url },
                                                         { :scope =&gt; 'https://www.google.com/analytics/feeds/' })
  session[:request_token] = @request_token.token
  session[:request_secret] = @request_token.secret

  redirect_to("#{@request_token.authorize_url}&amp;amp;oauth_callback=#{CGI.escape(callback_account_authorizations_url)}")
end
&lt;/pre&gt;


&lt;p&gt;From the users' point of view, they'll get a link to click to "enable Google
Analytics", which will take them to the &lt;code&gt;new_authorizations_url&lt;/code&gt; corresponding
to the action above. This will then auto-redirect them to the Google
authorization page, which will resemble the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/static/google-analytics-integration/google-oauth.png" alt="Google Authorization"/&gt;&lt;/p&gt;

&lt;p&gt;After they authorize us to access their data, they'll be redirected back to
our callback URL. When Google redirects to this URL they'll include an
important query parameter that we need to create our precious access token:
the &lt;strong&gt;OAuth verifier&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's what the callback action should look like in our controller:&lt;/p&gt;

&lt;pre class='brush: ruby;'&gt;
def callback
  unless session[:request_token] &amp;amp;&amp;amp; session[:request_secret] 
    flash[:error] = "No authentication information was found in the session. Please try again."
    redirect_to(root_url)
    return
  end

  unless params[:oauth_token].blank? || session[:request_token] ==  params[:oauth_token]
    flash[:error] = "Authentication information does not match session information. Please try again."
    redirect_to(root_url)
    return
  end

  @request_token = OAuth::RequestToken.new(GoogleAuth.consumer, session[:request_token], session[:request_secret])
  @access_token = @request_token.get_access_token(:oauth_verifier =&gt; params[:oauth_verifier])
    
  session[:request_token] = nil
  session[:request_secret] = nil

  current_user.update_attributes(:access_token =&gt; @access_token.token, :access_secret =&gt; @access_token.secret)

  flash[:notice] = "You have successfully linked your Google Analytics account."
  redirect_to(account_path)

rescue Net::HTTPServerException =&gt; e
  case e.message
  when '401 "Unauthorized"'
    flash[:error] = "This authentication request is no longer valid. Please try again."
  else
    flash[:error] = "There was a problem trying to authenticate you. Please try again."
  end 

  redirect_to(:action =&gt; 'new')
end
&lt;/pre&gt;


&lt;p&gt;The first two conditional blocks just check to make sure that the token and
secret are found in the user session and that the token provided by Google in
the parameters matches the one that the user previously established. The next
step is creating an access token from the verifier that Google sent back to
us. This is the token we'll use to access the GA resources for the user going
forward.&lt;/p&gt;

&lt;p&gt;We can then clear out the session variables and update the user model with the
access token and secret that we've obtained. By storing these values in our
database, and associating them with the user account that authorized us, we
can rebuild the tokens we need to obtain analytics data from Google at any
time, without having to go through this process again.&lt;/p&gt;

&lt;p&gt;Here's the controller code for our &lt;code&gt;AuthorizationsController&lt;/code&gt; in its entirety
(including a method to de-authorize us):&lt;/p&gt;

&lt;pre class='brush: ruby;'&gt;
class AuthorizationsController &amp;lt; ApplicationController
  before_filter :require_user

  def new
    @request_token = GoogleAuth.consumer.get_request_token({ :oauth_callback =&gt; callback_account_authorizations_url },
                                                           { :scope =&gt; 'https://www.google.com/analytics/feeds/' })
    session[:request_token] = @request_token.token
    session[:request_secret] = @request_token.secret

    redirect_to("#{@request_token.authorize_url}&amp;amp;oauth_callback=#{CGI.escape(callback_account_authorizations_url)}")
  end

  def create
    redirect_to(:action =&gt; :callback)
  end

  # oauth callback
  def callback
    unless session[:request_token] &amp;amp;&amp;amp; session[:request_secret] 
      flash[:error] = "No authentication information was found in the session. Please try again."
      redirect_to(root_url)
      return
    end

   unless params[:oauth_token].blank? || session[:request_token] ==  params[:oauth_token]
     flash[:error] = "Authentication information does not match session information. Please try again."
     redirect_to(root_url)
     return
   end

    @request_token = OAuth::RequestToken.new(GoogleAuth.consumer, session[:request_token], session[:request_secret])
    @access_token = @request_token.get_access_token(:oauth_verifier =&gt; params[:oauth_verifier])
    
    session[:request_token] = nil
    session[:request_secret] = nil

    current_user.update_attributes(:access_token =&gt; @access_token.token, :access_secret =&gt; @access_token.secret)

    flash[:notice] = "You have successfully linked your Google Analytics account."
    redirect_to(account_path)

  rescue Net::HTTPServerException =&gt; e
    case e.message
    when '401 "Unauthorized"'
      flash[:error] = "This authentication request is no longer valid. Please try again."
    else
      flash[:error] = "There was a problem trying to authenticate you. Please try again."
    end 

    redirect_to(:action =&gt; 'new')
  end
  
  def destroy
    current_user.update_attributes(:access_token =&gt; nil, :access_secret =&gt; nil)
    flash[:notice] = "You have successfully removed your Google Analytics account link."
    redirect_to(account_url)
  end
end
&lt;/pre&gt;


&lt;p&gt;And example routes:&lt;/p&gt;

&lt;pre class='brush: ruby;'&gt;
ActionController::Routing::Routes.draw do |map|
  map.resource :authorizations, :collection =&gt; { :callback =&gt; :any }
  …
end
&lt;/pre&gt;


&lt;p&gt;At this point we're all set up to use Google Analytics data in our
application. So we should probably do something interesting with it.
Fortunately, Tony Pitale has made interfacing with GA itself -- that
is, once OAuth connection has been established -- insanely easy with his &lt;a
href="http://github.com/vigetlabs/garb"&gt;Garb gem&lt;/a&gt;. To use Garb we can
simply create a new Garb session object using a previously established OAuth
access token (I personally like to wrap this up into a method on the User
model):&lt;/p&gt;

&lt;pre class='brush: ruby;'&gt;
session = Garb::Session.new
session.access_token = OAuth::AccessToken.new(GoogleAuth.consumer, user.access_token, user.access_secret)
&lt;/pre&gt;


&lt;p&gt;And then we can retrieve account and profile data from Garb...&lt;/p&gt;

&lt;pre class='brush: ruby;'&gt;
accounts = Garb::Account.all(session)
profile_id = accounts.first.profiles.first.id
&lt;/pre&gt;


&lt;p&gt;In addition to accessing raw account info, stat values, etc, you can create
some pretty elaborate "reports" in Garb. A sample report might look like:&lt;/p&gt;

&lt;pre class='brush: ruby;'&gt;
class PageViewReport
  extend Garb::Resource

  metrics :unique_pageviews
  dimensions :page_path

  filters { eql(:page_path, '/') }
  filters { eql(:page_path, '/blog') }
end

report = PageViewReport.results(profile_id, :session =&gt; session,:start_date =&gt; 10.days.ago, :end_date =&gt; Time.now)
report[0].page_path
# =&gt; '/blog'
report[0].unique_pageviews
# =&gt; 500
&lt;/pre&gt;


&lt;p&gt;Tony does a much better job explaining
&lt;a href="http://wiki.github.com/vigetlabs/garb/building-a-report"&gt;how reports
work&lt;/a&gt;, and what you can do with them. I'd suggest checking out his
&lt;a href="http://wiki.github.com/vigetlabs/garb/"&gt;Wiki&lt;/a&gt;,
&lt;a href="http://github.com/vigetlabs/garb"&gt;GitHub repository&lt;/a&gt;, or the
series of posts over at
&lt;a href="http://www.viget.com/extend/introducing-garb-access-the-google-analytics-data-export-api-with-ruby/"&gt;Viget
Extend&lt;/a&gt; for more information on Garb.&lt;/p&gt;

&lt;p&gt;To present this data to a user, we can now toss together some pretty graphs and
charts using my favorite JavaScript graphing library, &lt;a
href="http://g.raphaeljs.com"&gt;raphael.js&lt;/a&gt;. This is a good way to visualize
browser marketshare data, page access trends, and other analytical data that
they might want to drill down on.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>How to Accept Self-Signed SSL Certificates in Selenium</title>
    <link href="http://mogotest.com/2010/04/13/how-to-accept-self-signed-ssl-certificates-in-selenium" />
    <updated>2010-04-13T00:00:00-04:00</updated>
    <id>http://mogotest.com/2010/04/13/how-to-accept-self-signed-ssl-certificates-in-selenium</id>
    <content type="html">&lt;p&gt;Accessing pages with self-signed SSL certificates in Selenium can be a bit tricky.  The core of the issue is every major browser raises a security issue when accessing a page using a self-signed SSL certificate.  Since this security check takes effect before the Selenium Javascript can execute, there's no way to instruct the browser to accept the certificate.&lt;/p&gt;

&lt;h2&gt;Selenium as a Proxy Server&lt;/h2&gt;

&lt;p&gt;As it turns out, there is a solution built into Selenium, but there's some work involved to get it going properly.  Unless you use the &lt;code&gt;-avoidProxy&lt;/code&gt; argument when you start up the Selenium server, it will serve as a proxy for connections originating on localhost.  If you start the Selenium server with the &lt;code&gt;-trustAllSSLCertificates&lt;/code&gt; argument the proxy will be able to handle any type of SSL certificate issue for any site.  The corollary to using Selenium server as a proxy is that your browser sessions need to be configured to use the Selenium server as a proxy.  It should be noted that this is not the same as proxy injection mode; Selenium is not injecting itself into your page, it's simply proxying the content for you.&lt;/p&gt;

&lt;h2&gt;Configuring the Selenium Browser Launchers&lt;/h2&gt;

&lt;p&gt;You configure the browser's proxy settings through the browser launcher.  Some of the provided launchers do this already.  For Internet Explorer you can use the &lt;code&gt;*iexploreproxy&lt;/code&gt; launcher and for Firefox you can use the &lt;code&gt;*firefoxproxy&lt;/code&gt; launcher.  Another option is to use a custom browser launcher.  We do this with both Firefox and Internet Explorer and the code can be found on our &lt;a href="http://github.com/mogo/selenium"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We found the default chrome launcher for Firefox is very close to what we want and didn't want to have to manage our own custom profiles.  So we use that launcher as a base and modified it such that if Selenium server is started with &lt;code&gt;-trustAllSSLCertificates&lt;/code&gt; option then then generated Firefox profile will set up the Selenium server as the proxy.  The &lt;a href="http://gist.github.com/364250"&gt;patch&lt;/a&gt; actually modifies the &lt;code&gt;*firefox&lt;/code&gt; launcher, but a custom launcher is likely a safer option for you.&lt;/p&gt;

&lt;p&gt;The reason we use a custom launcher with Internet Explorer is that we've experienced reliability issues with the &lt;code&gt;*iexploreproxy&lt;/code&gt; launcher.  We've found &lt;code&gt;*iexplore&lt;/code&gt; to be more reliable so our custom launcher simply configures Internet Explorer to use Selenium as its proxy server and then uses HTA to perform the browser automation functions, similar to how &lt;code&gt;*iexplore&lt;/code&gt; operates.  The &lt;a href="http://github.com/mogo/selenium/blob/master/remote/server/src/java/org/openqa/selenium/server/browserlaunchers/InternetExplorerMogoLauncher.java"&gt;code for this launcher&lt;/a&gt; is also available in our GitHub repository.&lt;/p&gt;

&lt;p&gt;An extra step is required for proxying SSL content with Internet Explorer.  Selenium bundles a special certification authority (CA) certificate that is used to trust all the other SSL certificates.  Windows will not trust this CA certificate until it is installed in the trusted root store.&lt;/p&gt;

&lt;h2&gt;Installing the CyberVillains Certificate on Windows&lt;/h2&gt;

&lt;p&gt;The following figures show the steps necessary to install the CyberVillains certificate on Windows.  This is only necessary if you're using Internet Explorer.  Selenium is able to manipulate Firefox to trust the certificate with its custom-built profile.&lt;/p&gt;

&lt;p&gt;The CyberVillains certificate is bundled in the most recent Selenium RC releases.  If you download the distribution and extract it, you should be able to get going starting with Figure 1.  In the explorer address bar in Figure 1 you can see where to find the certificate.  You must substitute the base path (C:\, here) with wherever you extracted the files.&lt;/p&gt;

&lt;div class="figure"&gt;
  &lt;img src="/images/static/how-to-accept-self-signed-certificates-in-selenium/cybervillains_certificate.png" /&gt;

  Figure 1: Double-click the CyberVillains certificate in the selenium server distribution.
&lt;/div&gt;




&lt;div class="figure"&gt;
  &lt;img src="/images/static/how-to-accept-self-signed-certificates-in-selenium/install_certificate.png" /&gt;

  Figure 2: Install the CyberVillains certificate.
&lt;/div&gt;




&lt;div class="figure"&gt;
  &lt;img src="/images/static/how-to-accept-self-signed-certificates-in-selenium/certificate_import_wizard.png" /&gt;

  Figure 3: Click through the SSL certificate import wizard.
&lt;/div&gt;




&lt;div class="figure"&gt;
  &lt;img src="/images/static/how-to-accept-self-signed-certificates-in-selenium/choosing_the_certificate_store.png" /&gt;

  Figure 4: Choose the Trusted Root Certification Authorities certificate store.
&lt;/div&gt;




&lt;div class="figure"&gt;
  &lt;img src="/images/static/how-to-accept-self-signed-certificates-in-selenium/finish_wizard.png" /&gt;

  Figure 5: Complete the import.
&lt;/div&gt;




&lt;div class="figure"&gt;
  &lt;img src="/images/static/how-to-accept-self-signed-certificates-in-selenium/security_warning.png" /&gt;

  Figure 6: Accept the security warning.
&lt;/div&gt;




&lt;div class="figure"&gt;
  &lt;img src="/images/static/how-to-accept-self-signed-certificates-in-selenium/successful_import.png" /&gt;

  Figure 7: Wrap everything up.
&lt;/div&gt;


&lt;br /&gt;


&lt;p&gt;At this stage everything is set up and you should be able to run your Selenium server with the &lt;code&gt;-trustAllSSLCertificates&lt;/code&gt; argument without any problems.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;To recap, accepting self-signed certificates in Selenium is a two-staged process.  You need to instruct the Selenium server to trust all SSL certificates and then tell the browser to use the Selenium server as a proxy.  You may find that creating a custom browser launcher is the best way to configure your browser's proxy settings.  After doing this, you'll be able to test sites running on domains with self-signed and invalid SSL certificates.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Selenium Grid News</title>
    <link href="http://mogotest.com/2010/03/31/selenium-grid" />
    <updated>2010-03-31T00:00:00-04:00</updated>
    <id>http://mogotest.com/2010/03/31/selenium-grid</id>
    <content type="html">&lt;p&gt;It's no secret that we're big fans of the &lt;a href="http://seleniumhq.org"&gt;Selenium&lt;/a&gt;
project. Selenium's screen capture facilities provide a key bit of the
infrastructure that Mogotest runs on. And, since we're distributing those jobs
to our cloud-based render agents, we need a way to manage that, too. That's
where Selenium Grid comes into play.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://selenium-grid.seleniumhq.org"&gt;Selenium Grid&lt;/a&gt; is basically a framework
for distributing Selenium tasks across many hosts (in our case, via our EC2
render cluster). This allows us to run our tests in parallel and deliver
results to users as quickly and efficiently as possible.&lt;/p&gt;

&lt;p&gt;Grid was originally developed and maintained by &lt;a href="http://ph7spot.com"&gt;Phillippe
Hanrigou&lt;/a&gt; of ThoughtWorks and has received contributions
from numerous people, including Mogo co-founder Kevin Menard. &lt;a href="http://ph7spot.com/blog/selenium-grid-needs-a-new-maintainer"&gt;Earlier this
month&lt;/a&gt;,
Phillippe announced that he would be stepping down from the project and was
looking for a new maintainer. Kevin was one of the folks who was nominated to
fill his shoes, and it now looks like &lt;a href="http://ph7spot.com/blog/new-selenium-grid-maintainer"&gt;he's officially got the
gig&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What does this announcement mean for Selenium Grid? It means that the
project will have an active maintainer who (despite his obvious personality
flaws) has a serious commitment to pushing the project codebase forward,
fixing bugs, and fostering community involvement -- things that every mature
open source project needs. Good stuff! And it's good for us, too. For exactly
the same reasons.&lt;/p&gt;

&lt;p&gt;So congratulations on the new responsibility, Kevin. I'm definitely looking
forward to seeing how Se Grid evolves under the new project leadership.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Web Development is Hard Work</title>
    <link href="http://mogotest.com/2010/03/10/hello-mogo" />
    <updated>2010-03-10T00:00:00-05:00</updated>
    <id>http://mogotest.com/2010/03/10/hello-mogo</id>
    <content type="html">&lt;p&gt;Web development can really suck. If you're building websites or applications
that run on the Web, you're juggling a lot of different technologies: HTML,
CSS, JavaScript, one or more of a dozen different server-side languages,
database administration, blah blah blah.&lt;/p&gt;

&lt;p&gt;And, because you're a good developer -- the kind who wants their work to look
and behave consistently for your users -- you want to test as much of this
stuff as possible. Unit tests make a huge difference in the way we write and
refactor code, but testing the actual end user experience... that's harder to
do.&lt;/p&gt;

&lt;p&gt;As web developers ourselves, we're acutely aware of some common pain points.
One of the biggest ones is cross-browser testing. Doing it by hand is downright
painful, and requires a veritable QA lab of different platforms and browsers.
And different versions of browsers. And service patches. And updates.
That can be a lot of work, especially if you're a small shop, overworked, or
simply have better things to deal with.&lt;/p&gt;

&lt;p&gt;We're building Mogotest to make testing your websites and Web-based
applications easier. So you can spend less time checking your site in
different browsers and more time concentrating on the features that make your
project truly unique.&lt;/p&gt;

&lt;p&gt;What we do right now:
* Cross-browser render testing
* View comparison tools
* Validation and verification&lt;/p&gt;

&lt;p&gt;Where we want to get to (the cool stuff):
* Full-on view-level regression testing
* Providing tools that make it easier for you to detect and fix common
rendering problems&lt;/p&gt;

&lt;p&gt;The service is in private alpha right now. But if you're interested, please
&lt;a href="http://mogotest.com"&gt;sign up&lt;/a&gt; and we'll get you an invitation
as soon as more are available.&lt;/p&gt;

&lt;p&gt;Thanks for your interest in Mogo!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*back to work*&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  
</feed>

