Apr 12

Hi All,

When you are using watir-webdriver for web testautomation, you might encounter problems that are not be easy to debug. For example interaction with page elements such as links or buttons that are hidden. Or locating elements in other iframes. One easy way to see what is going on is by interacting with your web browser through the command line!

To make this happen, make sure you have;

  1. a recent version of ruby installed (1.9.3 or later)
  2. a recent version of firefox installed
  3. the ruby gem ‘watir-webdriver’ installed;
gem install 'watir-webdriver'

Now, start the Interactive Ruby Shell…
In this irb, after loading ‘watir-webdriver’, you can start firefox with one command and interact with it right away!

sC-MBP:~ sCblogger$ irb
irb(main):001:0> require 'watir-webdriver'
=> true
irb(main):002:0> b = Watir::Browser.new
=> #
irb(main):003:0> b.goto "www.google.com"
=> "http://www.google.nl/"
irb(main):004:0> b.button(:text => /Google zoeken/).id
=> "gbqfba"
irb(main):005:0>

Screen Shot 2013-04-12 at 10.59.17 AM

NOTE: with ruby 1.8.7 or earlier, you’d have to require ‘rubygems’ first before require ‘watir-webdriver’

Dec 02

Introduction

 

Hi Again,

In this post we would like to explain a bit more about the mobile test automation that we are using here at spriteCloud. The past years we have seen that the mix of cucumber with selenium webdriver has been extremely powerful. This setup allows for test automation that is, besides easy to setup and maintain once you get the hang of it, understandable and easy to expand for any stakeholder in your project. We are using this same setup now for testing native mobile applications and it works like a charm!

We will start with mobile test automation for android. For this test automation we are using calabash-android which is basically a mix of cucumber with robotium under the hood…

 

Step 1 – Setup your environment

 

First, you need to get all your libraries sorted. This should be fairly easy to achieve since you just need to;
- Install ruby if you dont have it installed already
- install calabash-android:

gem install calabash-android

Depending on your testscenarios you might need some more libraries but you’ll get there along the way.

Now, make a root folder where you want to store your test automation files and create the skeleton files for your test automation by running the following command:

calabash-android gen

This step is also well explained at the installation section of the calabash-android project

 

Step 2 – Use the default debug build key and signature

 

Well done, you’ve got all the requirements to build your test automation suite. Well, you’d need an app as well. Plus you’d need to sign it and use the exact same key and credentials for your calabash testserver, else it wont be able to install and run it on the emulator or device. Although creating a key and use it to sign your apk is all explained on the android developers pages, the easiest would be to just have the test automation use the default debug key that android uses (which is being generated when you build your application). The only thing you need todo for that is to create/edit a .calabash_settings file in the root directory of your test automation folder and point to that keystore file. For example:

{
  "package_name":"debug.keystore",
  "api_level":"14",
  "keystore_location":"./features/support/debug.keystore",
  "keystore_password":"android",
  "keystore_alias":"androiddebugkey",
  "keystore_alias_password":"android"
}

NOTE: api_level obviously depends on what android platform you are building your app on so make sure to have that set correctly.

 

Step 3 – Test the test setup

 

There you go. Now your test setup should be all set. You dont have any test scenarios yet, but running calabash should show you if you have everything set up properly!

calabash-android run <link_to_your_android_debug_build.apk>

In the features folder you can place your scenarios. Information about creating feature files can be found in our blog about cucumber and web testing.

 

For iOS you say?…

 

Yes, there is a gem called calabash-ios. This is working somewhat different since there is no robotium under the hood. Its too much work to cover that here, so hopefully we are able to give some more information for you at a later stage.

‘Happy test-automationing’!

Apr 23

Introduction

 

Hi All,

In this post we explain how to detect Javascript Errors in firefox using selenium, watir webdriver and cucumber. If you are unfamiliar with these frameworks you can read up on our previous post about Web testing with cucumber.

 

Get JSErrorCollector

First, you need to get JSErrorCollector.xpi which you can get here. Then, store it under features/support/extensions in your cucumber project location.

 

Add JSErrorCollector.xpi to your browser profile

require 'rubygems'
require 'selenium-webdriver'
require 'watir-webdriver'
require 'logger'
 
#Start the logger
$log = Logger.new('log/selenium.log')
#Create a profile
profile = Selenium::WebDriver::Firefox::Profile.new
 
#Add JS error detection to the profile!
profile.add_extension "features/support/extensions/JSErrorCollector.xpi" rescue p "Cannot add JSErrorCollector.xpi to profile"

 

Launch a browser using the profile you created

Now you can launch a new browser instance using:

$BROWSER = Watir::Browser.new 'firefox', :profile => profile
$BROWSER.goto "http://www.spritecloud.com"

 

When the JSErrorCollector is installed successfully, you will see the error collector counter in the bottom right of the launched browser as displayed in the image below.

Collect the JS errors

First off, we create a separate method to get the JS errors formatted how you want to display them when one or more JS errors are detected.

#Function that returns a string that presents the details of the occurred JS errors
def get_js_error_feedback()
  jserror_descriptions = ""
  begin
    jserrors = $BROWSER.execute_script("return window.JSErrorCollector_errors.pump()")
    jserrors.each do |jserror|
      $log.debug "ERROR: JS error detected:\n#{jserror["errorMessage"]} (#{jserror["sourceName"]}:#{jserror["lineNumber"]})"
 
      jserror_descriptions += "JS error detected:
   #{jserror["errorMessage"]} (#{jserror["sourceName"]}:#{jserror["lineNumber"]})
"
    end
  rescue Exception => e
    $log.debug "Checking for JS errors failed with: #{e.message}"
  end
  jserror_descriptions
end

 

Raise exception when JS error is detected

When using cucumber, you can create a hook after every teststep. In this hook we raise an exception when one or more JS errors are detected.

AfterStep do |scenario|
  raise get_js_error_feedback() unless get_js_error_feedback().empty?
end

Note that this is a Collector, so at the end of each execution, the JS errors of all the visited pages are collected. For speeding up the tests, you can do the check after the end of each scenario (use hook AfterScenario) and cleanup the list after that.

Good Luck!

Apr 22

Hi All,

We have seen quite some people having trouble getting a proper test automation setup using cucumber and watir-webdriver or selenium-webdriver. Here we describe the minimum number of steps to get your cucumber with watir/selenium-webdriver up and running.

Step 1 – Install Ruby


Download and install rubyinstaller-1.9.2-p180.exe.

Explanation/details:

rubyinstaller-1.8.7-p334.exe would also work

Step 2 – Extract DevKit


Download and extract DevKit-tdm-32-4.5.1-20101214-1400-sfx.exe to a folder you like.

Explanation/details:

Make sure you create a new folder, it extracts the lib and bin folders to that location, there is no root folder such as DevKit for example.

DevKit is needed because Cucumber requires the json gem. Without installing DevKit you would get the error:
ERROR: Error installing cucumber:
The 'json' native gem requires installed build tools.

Please update your PATH to include build tools or download the DevKit
from 'http://rubyinstaller.org/downloads' and follow the instructions
at 'http://github.com/oneclick/rubyinstaller/wiki/Development-Kit'

Step 3 – Install DevKit

Goto the root folder where you extracted DevKit and execute the commands:

ruby dk.rb init
ruby dk.rb install

Step 4 – Install the required gems

Execute:

gem update --system
gem install rspec --no-ri --no-rdoc
gem install win32console --no-ri --no-rdoc
gem install watir-webdriver --no-ri --no-rdoc
gem install cucumber --no-ri --no-rdoc

Explanation/details:

- Installing rspec because it is a commonly used gem.
- win32console supports colored output on the dos command line when executing the tests!
- watir-webdriver requires selenium webdriver, so that one will be installed always. If you only want selenium-webdriver, just do gem install selenium-webdriver instead.

When creating an install_gems.bat file inlcuding these commands, make sure to use the CALL command, e.g:

CALL gem update --system
CALL gem install rspec --no-ri --no-rdoc
CALL gem install win32console --no-ri --no-rdoc
CALL gem install watir-webdriver --no-ri --no-rdoc
CALL gem install cucumber --no-ri --no-rdoc

Step 5 – Start with your Cucumber and Webdriver setup

New to cucumber? Have a look at our Web Testing With Cucumber blog!

Aug 29

Evaluating the success of test automation is a lot like pagan mystic voodoo; there is a lot of activity involved, much chanting and ranting; and a fair amount of ritual, with the end result being completely valid, or highly dubious.

We here would all believe that there is value in automation, otherwise we wouldn’t be part of this group (let alone reading these very wordy forum posts of mine), but how do we know what that value is? Can it be stated in some kind of metrics that make sense to the world at large, or is it still mainly anecdotal?

I have often had to face this scenario of explaining why as a test manager I’ve put resources from my group into test automation. There are the obvious answers such as “it saves us time in regression testing basic scenarios that are manually intensive”. Login and registration functionality being a fine example. But can this be equated in some way with time invested up front VS time saved per test cycle where the automation is used.

Then of course there is the indirect value to consider. Test automation doesn’t find defects in the first instance, that is up to the test techniques that are all manually performed by a tester. So automation isn’t something that contributes immediate value, but value that starts after a certain period of time on a software project. Test automation scripts degrade over time as well, hence they require maintenance. If the maintenance phase is shortened or skipped entirely because of project delivery deadlines, then over time the automation scripts become useless. Hence more time is required to keep scripts valid with every release.

So it seems to me that some form of metric analysis could be performed, but would it really be useful? Is the value of test automation really something that can be quantified, or is it destined to be like Zen; you either get it or you don’t?

Thoughts anyone?

Andy.

Tagged with:
Jul 27

Much of the software development in website development is done using agile methods. Automation is usually necessary to keep up with the speed.

It’s not really a question of whether automation is useful. Only a few people would rather repeat the same tasks many times every day then to let a computer do them. The question is whether the benefits are bigger then the costs. There will always be costs; automation is an investment. Businesses expect a return for their investment. There are several advantages:

  • Requiring less manual work to reach the same test coverage
  • Being able to use testing resources for higher value work improving the user experience
  • Happier users -> more users

 

How to get started?

 

One of the critical parts in building test automation and automation suites is to have the right people to do it. There are other factors too, which I’ll briefly go through in this post. Tools, planning and working methods are other important factors.

 

Test automation suite?

 

What is it?

A test automation suite can be many things. It can and will evolve during its lifetime. The word test automation suite, at least for me, conveys a message of something massive, something that took a long time to build, covering the whole site functionality. That’s one definition, but there is no reason not to use a simpler, more agile approach.

A suite can be as small of automating a specific part of a site, for example, top navigation or a registration form. Anything, which needs a lot of steps to cover with every build, is a good candidate for automation. Can’t these things be tested manually then? Yes, but testers are humans too, you know. They will not be happy clicking the same 100 links or entering the 100 different email addresses required for good coverage. Does it matter that the tester is not happy about something. Well, that’s more of a HR question, but for me, it does matter. People need to be motivated to achieve the best results.

And the main reason for doing any testing is to achieve good quality. Saving the time from manually testing the forms and navigation will allow the tester to really do his/her job and concentrate on the more challenging test areas, for example, making sure the user experience of your site’s users is as good as possible.

And to be honest, no one will test all the links manually with every build. It’s only a matter of time before there is a serious problem when something important is missed in testing.

 

Okay, okay, we need automation. What next?

 

Requirements for successful automation project?

Here is a list of things that are important for a successful automation project.

  1. Deep understanding of web technologies, HTML page elements. Mind you, this is hopefully something your testing team already understands.
  2. Co-operation between development and QA teams in terms of communication about upcoming chances
  3. Time. It will take some time to implement the automation. It will still be worth it, in many cases. Just remember to allocate some time for it. It’s important to keep working on automation iteratively, building more coverage as the site and the development work progresses. There will never be a two to four week period in the end of the project where you can just concentrate on building automation. Really. There isn’t.
  4. Stability. If the site changes every day, it’s better to not start building an extensive suite. Again, start with the areas that are more stable. If not, you might face the chicken and the egg problem. You need a stable site to build automation but the site does not get stable when you don’t have it.
  5. Iterative (agile) approach. Start from a single area in one browser. While doing this, you will see how well the automation works with your site. Once you are comfortable with the automation and how it works with your site, increase the coverage and expand to other browsers and platforms.
  6. Tools. Use a tool set that’s easy to maintain. Use modern tools like Cucumber for writing the test cases and combine it with either Watir or Selenium. Whatever tool you use, make sure you can reuse your code. Cucumber is essentially a collection of navigation commands on your site combined with test cases that can be understood by other people, especially business analysts. They could even give you a hand in the test case creation by documenting the requirements in a format that can be used for test cases. Ideally, when using Cucumber, the requirements are the test cases.
  7. Test automation is a tool to increase your test coverage, do not make it the software development project. You will not be allowed to keep working on the automation for months and months. While it is important to get the automation done properly, there is a risk that too much effort will be allocated for it. Like in any other form of testing, there is a trade-off between the time spent and the results achieved. 80-20 rule applies here too. Test automation is a tool to make your development project more successful in terms of quality and schedule. When you achieve that, you can be satisfied with the results.

 

The people

 

Can your average QA person do automation in a maintainable and reusable way? Most likely not. It requires a different skill set then manual testing. Or should I say, other skills in addition to the functional tester skills. A good solution is to have a team where some of the people are good in planning testing and test cases while others have the coding skills to maintain and build the test automation. If the team does not have the people with coding skills, most people start to automate testing with the help of a tool recording test cases. This will in most cases lead to major difficulties in maintaining the tests in the future. It can also be difficult to customize the tests for data-driven testing.

Required competencies

Automation requires development skills. You don’t need to be a high-level C++ programmer to create automation scripts. However, knowing how to implement code in a managed way will be necessary to get the automation done. And it is not only about completing the initial set of automation tests. The software/website you’re testing will typically receive updates every day/week. Some of those changes are going to break your test automation. Even if all the functionality on the site still works, some elements could have been moved or renamed causing the test automation not to find the element anymore. Elements on the page will need to be identified with the element attributes (for example, link text) or XPATH expressions, which are powerful but rigid. This is really the part where good understanding of HTML is required.

Software development practices

Maintaining any software, also test automation will benefit from good development process. One of the most important ones is using version control systems, for example, Subversion or git. It will enable maintaining the current version of the automation and tracking the changes done to it as well as branching your scripts for the current production system and the development version if there are major differences.

 

Development guidelines

 

Having a set of development guidelines to support the automation is needed to minimize unnecessary changes to the site. A big part of the technical implementation of test automation has to do with locating HTML elements on the page. It is good to establish naming conventions for the elements, and then stick to it. While it might be / is a good idea to fix naming of an element from something that’s obviously wrong, it can potentially cause test cases to fail. A typical case of this is could be something like renaming an element to something that’s clearer to other users:


<div>
  <ul class="top-nav">
    <li>Item 1</li>
    <li>Item 2</li>
  </ul>
</div>

Renaming the above unordered list would require the following change to an XPATH expression identifying the element:

//ul[@class='top-nav']  ->  //ul[@class='top-navigation']

While this change does make sense, it can easily cause automation tests to fail. The fact that test cases sometimes fail is not really a problem; it’s a fact of life that needs to be managed by allocating time for maintenance work.

 

Allocating time for automation

 

The project manager creates a plan for his project. The plan includes time for QA after the development work is completed.

Project of 6 months:

  • 2 month for requirements / user stories
  • 3 months for development
  • 1 month for QA

Now, what happens when development time is increased by 30%. That’s not at all unrealistic, is it? Even with this relatively low delay percentage, the whole time to QA is basically eaten up by the development work. And there is of course a commitment for a customer to deliver on the agreed date. An additional complication is that there are most likely areas that have not been tested before the QA cycle is supposed to end.

The team will find defects on the last week of the project, things that should have been discovered 3 months earlier. Maybe there are areas that cannot be implemented at all with the current architecture.

This can, especially for a new team, lead to a situation where test automation is never taken into use in a proper way. There is not a lot of time, people are not familiar with the tools and enough progress is not made. In such a situation, management can easily loose faith in the usefulness of automation in general.

  spriteCloud Team

Mar 15

Agile testing methods

One of the keys to a successful agile software project is considering testing from the beginning. While in some projects, especially web projects, testing is sometimes an afterthought, one member of the team clicking away on the site for a while before deployment to production, which is not really a sustainable way of operation. At least not in a website that is used for something else then blogging. There’s nothing wrong with blogging, mind you, it’s just that the software is typically “ready” for use and people just change the content or posts. One way of achieving this goal is to use test driven development (TDD) or behavior driven development (BDD).

Test driven development

The word “driven” here refers to the way of writing the tests first, then the code to make the tests pass. Test driven development is more of a developer oriented approach, a more low level way of doing things.

Behaviour driven development

In BDD on the other hand, the tests are described in a natural language, which makes the tests more accessible to people outside of development or testing teams. It can describe the functionality as specifications do.

Cucumber

One implementation of BDD is Cucumber. Cucumber is a Ruby based test tool for BDD, Cucumber.  With Cucumber, the user describes the behavior of the system with natural language with some specific keywords. The process starts with creating a feature file, which explains a feature of the system and some scenarios of different test situations. As Cucumber doesn’t know how to interpret the features by itself, the next step is to create step definitions explaining it what to do when finding that step in one of the scenarios. The step definitions are written in Ruby. This gives much flexibility on how the test steps are executed. It can use and already has step definitions for Webrat, an acceptance testing tool for Ruby, which simulates a browser without Javascript support. But it can also be combined with a web automation framework like Watir to implement browser based web automation tests. Watir is what I’m going to be using in this example. This is not the traditional way of using Cucumber but works quite well anyway.

Feature

Here is an example of a simple feature description from a Cucumber feature file:

Feature: Website Navigation
  In order to navigate website pages
  I need to be able to click on menu item

The feature is an explanation of what we want to accomplish. It doesn’t really do much by itself but works are a specification for the system and the test.

Scenario

Now this feature needs to be tested with several scenarios. For example, user can be on a different page in the beginning of the test or the user can click on a different link. One scenario is shown below. It describes an operation, clicking on a menu item on our website:

Scenario: Going to page Services
  Given that I am on spriteCloud Home
  When I click on link Services
  Then the page title should be "spriteCloud - Services"

Step definitions

This is the part that we need to explain to Cucumber so that it knows what to do. In this case, we are using Watir with the Watir-webdriver gem. We also use RSpec gem to be able to use the should operation.

require 'spec'
require "watir-webdriver"

Then we define some constants, one for the site address and another one for referring to the browser. Note the syntax for starting an instance of Firefox with webdriver.

SITE = "www.spritecloud.com"
BROWSER = Watir::Browser.start(SITE, :firefox)
PAGES = {
  "spriteCloud Home" => "http://www.spritecloud.com/"
}

The hash PAGES is not really necessary in this case, but can be useful in a case when there is more data and pages involved. It is used for looking up a page URL based on page name in the scenarios.

Now that we covered the setup part, we need to start with the steps included in the scenario. The keyword “Given” is about setting up the test. We need to be on the home page in the beginning of the test.

Given /^that I am on (.*)$/ do |page|
  BROWSER.goto(PAGES[page])
end

Notice that the step syntax is formatted as a regular expression. Given is a keyword but everything else is basically just something that Cucumber can recognize as being part of your test. Let’s break that part down a bit:

  • Sentence starts with “Given” keyword. This is mandatory
  • What follows is a space and the words “that I am on”
  • Another regular expression (.*), which matches everything from “on ” until the end of the line “storing” it for later use for the variable page

Using the capturing group (.*) is important because it allows us to write more generic steps, where for example, the page where we are or the link that we are following is defined in the scenario, not in the step. This again allows for the less technical person to write tests without having to write Ruby code. It is of course also better programming practice not to write the same things multiple times and just changing a value.

Next keyword, “When” refers to an operation we do on the page. In this case, we want to click a link on the page. A link can be found with several different methods in Watir, here we use the :text method, which basically clicks on the link with the text we specify in the scenario.

When /^I click on link (.*)$/ do |link|
  BROWSER.link(:text, link).click
end

The last keyword in this example, “Then” refers to the result we are expecting. For the purposes of this example, we check that the page title is correct, i.e. the same as in the test scenario definition.
Then /^the page title should be "([^\"]*)"$/ do |title|
  BROWSER.title.eql?(title).should == true
end

Test Execution

This type of test can be run either during the implementation phase, which is the original purpose or later on when the site is fully ready. Even if the test was created during the implementation phase, it should still be run with every new release that goes out. It can even be used as a part of a stand-alone test set for the site.

Part of the power of Cucumber is the nicely formatted output displaying immediately the successful and the failed tests and test steps. Successful tests are colored green on the terminal and failed one, you guessed it, red.

mbp-2:features marko$ cucumber .
Feature: Website Navigation
	In order to navigate website pages
	I need to be able to click on navigation

  Scenario: Going to page Services                        
    Given that I am on spriteCloud Home                   
    When I click on link Services                        
    Then the page title should be "spriteCloud - Services"

1 scenario (1 passed)
3 steps (3 passed)
0m1.261s

Summary

This post only scratches the surface of what can be done with either Watir or Cucumber. They are both powerful test tools by themselves and combining them can be the basis for a successful test automation project. It all depends on the needs in your project.

Marko

Tagged with:
Mar 10

When you want to send tidy e-mails for marketing or other purposes you quickly run into the solution of using html within e-mails. In this post we will show you a code snippet that allows you to send such a html e-mail using standard python libraries.

However, before we start you should know that there are quite some articles and posts mentioning that creating html e-mails is a (very) bad idea. I believe it is ok sending out html e-mails these days; loads of support within e-mail clients has been added and you can see the number of html e-mails growing every day. However, there are a few caveats that you should be aware of! Lets list some of them first!..

CSS support

Obviously you want to use some CSS styles in your HTML e-mail. There are some differences with the support of CSS in an e-mail, support per css property can really differ per e-mail client/browser. Since it is really hard and not too much fun to try out all the different e-mail clients/portals you’d be better off to first see what html tags and css properties are actually supported. The best guide to this CSS Support maze in e-mail clients is probably this one.

When you are using CSS in your html e-mail, the best thing to do is to just put the CSS in a <style> tag in the <head>. Another possibility is to put a link to the CSS file but since that needs to be retrieved and might be blocked upon first view, so that is not the best solution. A problem here is that, as of writing, google gmail does not support a <style> tag or <link> to your CSS file in the <head>! Thus, if you want your style to be processed and visible in gmail, you have to include it in the html tags itself. Now, this is not the most ideal situation, but one thing you can do is to just put some minimal style in the html tags and put the rest in the CSS style tag. This approach has been used in the table below. This way, even when style tags are not supported you would still get the minimal ‘display tidyness’.

Catch e-mail clients where html e-mail is unsupported

With an html e-mail you have to change the “MIME type” of the email. Nearly all email clients support this nowadays, but it can still happen that you come across a client that doesnt. In the example you can see that, with a very simple setting, you can prevent the user from not receiving any feedback.

Always give a reference to the source/online example

Perhaps obvious, but it is advised to always have an example or reference to the content in the email online, and point to that. This way the receiver will not only be able to see the content in any situation, but you also have another option to drive the users to your website or service.

Reason and Un-subscribe

Another slightly obvious point; you should always give a reference to why someone receives the HTML e-mail (etc, subscribed to a newsletter..) so the receiver doesnt feel like he just received spam/unwanted marketing. Also an option to unsubscribe/stop receiving the emails should be included.

The example

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
 
def py_mail(SUBJECT, BODY, TO, FROM):
    """With this function we send out our html email"""
 
    # Create message container - the correct MIME type is multipart/alternative here!
    MESSAGE = MIMEMultipart('alternative')
    MESSAGE['subject'] = SUBJECT
    MESSAGE['To'] = TO
    MESSAGE['From'] = FROM
    MESSAGE.preamble = """
Your mail reader does not support the report format.
Please visit us <a href="http://www.mysite.com">online</a>!"""
 
    # Record the MIME type text/html.
    HTML_BODY = MIMEText(BODY, 'html')
 
    # Attach parts into message container.
    # According to RFC 2046, the last part of a multipart message, in this case
    # the HTML message, is best and preferred.
    MESSAGE.attach(HTML_BODY)
 
    # The actual sending of the e-mail
    server = smtplib.SMTP('smtp.gmail.com:587')
 
    # Print debugging output when testing
    if __name__ == "__main__":
        server.set_debuglevel(1)
 
    # Credentials (if needed) for sending the mail
    password = "mypassword"
 
    server.starttls()
    server.login(FROM,password)
    server.sendmail(FROM, [TO], MESSAGE.as_string())
    server.quit()
 
if __name__ == "__main__":
    """Executes if the script is run as main script (for testing purposes)"""
 
    email_content = """
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>html title</title>
  <style type="text/css" media="screen">
    table{
        background-color: #AAD373;
        empty-cells:hide;
    }
    td.cell{
        background-color: white;
    }
  </style>
</head>
<body>
  <table style="border: blue 1px solid;">
    <tr><td class="cell">Cell 1.1</td><td class="cell">Cell 1.2</td></tr>
    <tr><td class="cell">Cell 2.1</td><td class="cell"></td></tr>
  </table>
</body>
"""
 
    TO = 'receiver@email.com'
    FROM ='sender@mysite.com'
 
    py_mail("Test email subject", email_content, TO, FROM)

The example aftermath

The example requires you to change the FROM and TO email addresses and the password to send the email. If you do not use gmail to send the e-mail, you can probably find your smtp server settings here. The debugging option should give you a clear idea what the problem is, if something goes wrong regarding the sending process. There are also a lot of posts online about troubleshooting with python’s smtp lib.

When you execute the example and view the email in your gmail browser client you will see that the ‘in-tag-html’ styles are processed but not the style defined in the style tag. In other clients however all the styles in the example are processed.

Feb 01

Overview

This post covers the basics of managing Amazon Web Services (AWS) Elastic Cloud Computing (EC2) instances. Amazon EC2 service is the most well known cloud service operator providing computing instances and cloud storage in both Europe and the US. The service is charged by the hour of usage for the computing resources and by the amount of storage space used for the cloud storage. It is possible to choose from a number of different types of computing resources, which are priced according to several factors, for example, number of CPU’s or the amount of memory available to the node. The price increases with performance, for example, the price of a medium instance with 4 times the CPU power is 4 times the price of the small instance.

If the computing requirements are known beforehand, it is also possible to reserve the instances for 1 year or more paying an initial fee and getting lower monthly costs in return.

The service itself

Amazon provides a very nice service for people wanting to start using cloud computing resources with it’s easily accessible EC2 service. Getting starting with EC2 is quick once you know what you want to do with the nodes. The service is cheap enough to just start an instance and try out different options before making the decision on how to use it, too.

How to manage instances

As the whole point of a cloud service is the possibility to scale up to even a high number of instances based on the current demand, one of the most important topics is how to manage all of these nodes in an efficient way. It should be quick to start new ones when there is demand to do so, and also shutdown the nodes that are not needed thus saving unnecessary costs.

We will now take a look at different tools to manage the nodes and then go through the basic steps needed to setup your own instance.

EC2 Management tools

There is a number of options for managing the EC2 nodes. The most commonly used tools are:

  • AWS Management Console
  • Firefox Elasticfox Addon
  • Amazon EC2 tools
  • Custom scripts
AWS Management Console

The first one that the user comes in contact with is the AWS Management Console, which is part of Amazon AWS website that is accessible after signing up.

AWS Management Console

AWS Management Console

The dashboard can manage all aspects of the instances as can be expected so there are lots of different options available. The best was is to start it up, start some instances (Note: charges will apply) and try it out.

Elasticfox

Another way to manage the nodes is to use the Mozilla Firefox Elasticfox addon. The following screenshot does not really show the multitude of options the addon has. This view will show you a list of instances you have either starting up, running or stopped state. It will also show the terminated instances for an hour after termination.

Elasticfox Firefox addon

Elasticfox Firefox addon

Both of these tools are nice for starting up and instance once in a while or getting an overview of your nodes, but for the power-user or for managing a high number of nodes, they will be too cumbersome. And that’s where the command line tools come into the picture.

Amazon AMI Tools

The tools are available from Amazon, EC2 command line tools. First thing to do is to download the tools and unzip the package or install the RPM. To be able to use the tools, you need to get the private key and certificate from Amazon and set a number of environment variables. A good start is to create an .ec2 directory in your home directory and store the keys there.

Once that is done, you need to set the environment variables. On a Mac, you can add these lines to your .bash_login file:

export EC2_HOME=<directory where the tools are installed>
export EC2_URL=https://eu-west-1.ec2.amazonaws.com # your location
export EC2_PRIVATE_KEY=/Users/user/.ec2/pk-<YOUR KEY>.pem
export EC2_CERT=/Users/user/.ec2/cert-<YOUR CERT>.pem

The tool set consists of more than a 100 tools, which we are not going to go through here. The full documentation is available at CLI reference

Starting up an EC2 instance

The previous introduction will of course not suffice for understanding the tools, but is rather a starting point for the work.

The easiest way to start an instance is to click on the Launch Instance button on the dashboard.
The next step is to choose the image type you need. There are a number of different images types available, some of them from Amazon but most from other people that have been kind enough to provide their images for other peoples use.

Launch a new instance wizard

Launch a new instance wizard

The next step is to select the number of instances and the type of “hardware” to run on and the availability zone.

After that you need to choose a key pair to use for connecting to the instance from the ones you have already or create a new one. This is the key you need to use when connecting to the machine through SSH if running a UNIX/Linux instance. Last thing to do is to select a suitable firewall configuration. After that, review the instance parameters and start it. This is when Amazon starts charging you, so remember to shutdown instances you don’t need.

Next steps

While it is nice to have your own EC2 instance running, it’s usually not sufficient. When you terminate an instance, everything you have installed on it will be gone.

What you need is to build an AMI with all of the software you need, bundle it to an AMI and register it. Once that is done, you can just launch more instances of the same all having the correct software for your needs. You will also need some S3 storage for your files that you want to keep between the runs.

This can be done in several ways. The easiest one is to pick a publicly available image that is as close to your needs as possible. For example, one of the very nice Ubuntu images provided by Alestic. They have provided images for most Ubuntu versions and you can just pick one. Alestic images contain, for example, recent releases of Python and Ruby (1.8.7). Installing other software can be done with the usual Ubuntu tools.

It is also possible to build an image from scratch and then bundle it with the EC2 AMI tools.

Either way you do it, the image will be uploaded to S3 service for storage. Then the image can be registered to make it available for use in the dashboard or the other tools. You will need to choose the option “My AMI’s” from the EC2 dashboard when launching in an instance to use it.

And then you’re all set for some more serious work on the EC2.

Tagged with:
Jan 08

When you are automating your website tests, you will probably run into forms that need testing sooner or later. Even better (or worse), you wont be able to automate your tests at all if a simple login post is needed to access your site and you are unable to do so.

In python there are several approaches to post web-forms. In fact, there are too many to choose from. Therefore we created a list of the most used approaches, mention their differences and speak our preference. We dont go into much depth, but just show a simple example (and, if able, also prints the forms found on the page) and discuss the pro’s and cons.

The discussed libraries/approaches are:

  • basic urllib2 post support
  • Mechanize
  • Twill
  • ClientForm

There is also a library called Zope , able to post forms. The approach is much like the one from Mechanize, so I will not discuss that one here. When you are using pycurl, you probably end up using a different approach much like the urllib2 post support. An example for posting forms with pycurl can be found here.


Urllib2 post support:

import urllib, urllib2
page = 'http://www.mywebsite.com/myformpage.html'
raw_params = {'usern':'test_name','passw':'test_pass'}
params = urllib.urlencode(raw_params)
request = urllib2.Request(page, params)
page = urllib2.urlopen(request)
info = page.info()

If this works for you, and you dont find yourself using alot of different forms, this simple approach is the way to go, and there is no need to start using another library.

Pros: Simple, no other library needed

Cons: Very limited flexibility and support. Unable to detect any forms on a requested page. No success or failure feedback of a post.


Mechanize:

import mechanize
br = mechanize.Browser()
 
try:
	br.open(page)
	forms = br.forms()
	print 'Forms:'
 
	for form in forms:
		print 'form', form
		# Force try using the expected form
		br.select_form(name="form")
		br["usern"] = "test_name"
		br["passw"] = "test_pass"
		response = br.submit()
		content = response.get_data()
		br.close()
 
	except urllib2.HTTPError, e:
		sys.exit("%d: %s" % (e.code, e.msg))
	except IOError, e:
		print e
	except:
		pass

Pros: Easy to use,  Can detect forms on page.

Cons: Limited flexibility, Can choke on bad html.


Twill:

from twill.commands import go, showforms, formclear, fv, show, submit
 
go(page)
print "Forms:"
showforms()
 
try:
	# Force try using the first form found on a page.
	formclear('1')
	fv("1", "usern", "test_name")
	fv("1", "passw", "test_pass")
	submit('0')
	content = show()
	print 'debug twill post content:', content
 
except urllib2.HTTPError, e:
	sys.exit("%d: %s" % (e.code, e.msg))
except IOError, e:
	print e
except:
	pass

I have found that this library is the most robust against incorrect formatted html. It supports several ‘html cleanup libraries’ and is tidying up html by default. In some cases it was able to detect forms where others could not. The flexibility is still limited though.

Pros: Easy to use. Can detect forms on page. Robust against bad formatted html.

Cons: Limited flexibility, Not the fastest.


ClientForm:

import ClientForm, urllib2
request = urllib2.Request(page)
response = urllib2.urlopen(request)
forms = ClientForm.ParseResponse(response, backwards_compat=False)
print 'Forms:'
for form in forms:
	print form
try:
	# Force try using the expected form
	form = forms[0]
	form["usern"] = "test_name"
	form["passw"] = "test_pass"
	content = urllib2.urlopen(form.click()).read()
	check_success(content)
 
except urllib2.HTTPError, e:
	sys.exit("%d: %s" % (e.code, e.msg))
except IOError, e:
	print e
except:
	pass

As you can see, ClientForm can detect forms on a page and specifically select a form. Trying to set a value will only work if it that operation is really possible, so it tests itself already basically.

Pros: Great flexibility and support. Most comprehensive documentation and examples.

Cons: Html cleanup advised before form detection.


Last words (Conclusion, if you will):

I have found that most of the libraries are not very robust against incorrect html format. At time of writing I have found for example that a simple incorrect hr tag (<hr/> instead of <hr /> or <hr>) can break the detection of the form. a study with the incorrect hr tag showed that only twill was able to successfully detect the form, and none were able to do a successful post. It is therefore recommended to prettify your markup before ‘feeding’ it to your library. Although not very fast, the library you want to have a look at to do this is: BeautifulSoup.

Concluding I can say that, if urllib2 post support is sufficient, there is no need using other libraries. However, once the forms you start testing get more divers and the html pages contain incorrect html markup, you will find yourself struggling with posting forms where ClientForm gives a clear overview of what forms are available and knows all the possible fields and options.
So, due to the clear examples and documentation for ClientForm, and the biggest support and freedom for form field settings, this is definately my preferred library for posting forms.

Finally, make sure you support cookies, or e.g. trying to log in wont have the desired effect. The way to go here is using cookielib. An old but still useful example on usage can be found here.

Tagged with:
preload preload preload