Adventures in cron

Today I wanted to setup a cron job on my OSX machine. Basically I wanted to generate a report every day and have it copied to a shared google drive. Simple stuff. Setting up the cron job was fairly easy but did involve a little investigation and trial and error.

Creating my cron job

A quick search for cron on OSX led me here:

http://www.adminschoice.com/crontab-quick-reference/

So, I just run crontab -e from the command line and I get the crontab editor where I can add new cron jobs.

I wanted my cron job to run my already existing ruby script. After a quick google I found this:

http://www.ruby-forum.com/topic/3367718

So something like this will run a ruby script every 5 minutes.

"*/5 * * * * /usr/local/bin/ruby /local/myuser/rubyscript/script1.rb"

I modified the script for my own purposes – but nothing happened.
I run the script from the command line and I see the file being copied – but when cron runs it nothing shows up. It’s time to dig a bit deeper and find out whats happening

Searching the Logs

After some more searching I found out that cron on OSX logs to /var/log/system.log

http://superuser.com/questions/134864/log-of-cron-actions-on-os-x

In the log file I can see the cron job being run (/usr/sbin/cron[33137]) but no other hint’s to it’s success/failure. I do notice that the system is sending me some email though

Checking the Mail

I found out that I can pickup the system email by running mailx

http://www.askdavetaylor.com/how_do_i_read_system_mail_on_my_mac_os_x_system.html

After opening up my mail on the command line I see the problem in the latest mails – /bin/sh: bundle: command not found

Tuning the cron job

Looks like the cron can’t find bundle. I tried without bundle but then rake couldn’t be found.

After a little more searching I found that, by adding the path to my RVM, I was finally able to get cron to run my script.

http://stackoverflow.com/questions/6931889/cron-job-scheduled-but-not-running-rake-task

The final cron job looked something like:

*/15 * * * * cd /path/to/rails/app && /path/to/rvm 1.9.3-p392 do bundle exec rake MYRAKETASK

Finally everything is working and I found some out some useful information about cron, the logs and system mail!

Advertisements
Posted in Uncategorized | Leave a comment

Increasing Capybara’s page load timeout value

I recently had a problem with a page which wouldn’t load within the default page load time set by Capybara – resulting in the following Timeout error.

Timeout::Error (Timeout::Error)
      .rvm/rubies/ruby-1.9.2-p318/lib/ruby/1.9.1/net/protocol.rb:140:in `rescue in rbuf_fill'
      .rvm/rubies/ruby-1.9.2-p318/lib/ruby/1.9.1/net/protocol.rb:134:in `rbuf_fill'
      .rvm/rubies/ruby-1.9.2-p318/lib/ruby/1.9.1/net/protocol.rb:116:in `readuntil'
      .rvm/rubies/ruby-1.9.2-p318/lib/ruby/1.9.1/net/protocol.rb:126:in `readline'
      .rvm/rubies/ruby-1.9.2-p318/lib/ruby/1.9.1/net/http.rb:2219:in `read_status_line'
      .rvm/rubies/ruby-1.9.2-p318/lib/ruby/1.9.1/net/http.rb:2208:in `read_new'
      .rvm/rubies/ruby-1.9.2-p318/lib/ruby/1.9.1/net/http.rb:1191:in `transport_request'
      .rvm/rubies/ruby-1.9.2-p318/lib/ruby/1.9.1/net/http.rb:1177:in `request'
      .rvm/rubies/ruby-1.9.2-p318/lib/ruby/1.9.1/net/http.rb:1170:in `block in request'
      .rvm/rubies/ruby-1.9.2-p318/lib/ruby/1.9.1/net/http.rb:627:in `start'
      .rvm/rubies/ruby-1.9.2-p318/lib/ruby/1.9.1/net/http.rb:1168:in `request'

The Capybara documentation doesn’t make it immediately obvious how you would increase the page load timeout configuration value, but after some digging around, I eventually found a solution.

Capybara.register_driver :selenium_firefox do |app|
  client = Selenium::WebDriver::Remote::Http::Default.new
  client.timeout = 120 # <= Page Load Timeout value in seconds
  Capybara::Selenium::Driver.new(app, :browser => :firefox, :http_client => client)
end

Taken from => gist.github.com/922296

Posted in Uncategorized | Tagged , , , , , | Leave a comment

Cross Browser Testing in the Cloud with SauceLabs

When automating tests for web apps, one of the most difficult and time consuming tasks is ensuring functionality is consistant both across different browsers and across different operating systems. Traditionally this would involve lots of hardware and a huge manual setup and configuration overhead. SauceLabs helps to simplify this task by offering a cloud based service of virtual machines running a variety of operating systems and browser combinations upon which you can run selenium tests. The best thing about the service is that it is completely free. You are provided with a generous allowance of 200 minutes per month to get you started. If you need more then there are different plans available.

The following trivial example shows how I setup a test to run across multiple combinations of Operating Systems and Browsers using a simple cucumber feature file and a few simple Selenium2 commands written in Ruby.

Step 1 – Sign Up

Go to https://saucelabs.com/signup and sign up for a new account.

Step 2 – Setup

Follow the setup instructions at https://saucelabs.com/account?new=1

Step 3 – Write a test

The following feature file demonstrates how a simple test (in this case a search for a specific term in a search engine) can be specified to run on multiple browser and operating systems using a Gherkin example table.

Scenario Outline: search for cheese
    Given the environment setup of < OS > and < Browser > < BrowserVersion >
    When searching for "cheese" on bing
    Then the results should contain "CHEESE.COM - All about cheese!."

Examples: Valid Browser and OS Combinations
  | OS    | Browser | BrowserVersion |
  | XP    | Chrome  |                |
  | Win7  | IE      | 9              |
  | Linux | Firefox | 10             |

Step 4 – Write the implementation

The actual code to execute the above test covers multiple files. Rather than list them all here I have shared the entire project on github – see https://github.com/nathanbain/SauceLabsCucumberSelenium2Example.

Step 5 – Monitor the tests

Before running the tests, logon to your SauceLabs accounts test dashboard at https://saucelabs.com/jobs, so the tests can be monitored.

Step 6 – Run the tests

You can run your tests directly from the command line, or as I do, using rake. Using the rake file included in my github project I can run the test, which is tagged with the @complete tag, by running the following from the command line

rake cuke:complete

Step 7 – Watch your tests in realtime

A few seconds after starting the tests running you should see them appear on the test dashboard at https://saucelabs.com/jobs. From here you can monitor the status of running tests and also click on an individual test to view more detail of how the job is progressing.

Step 8 – Review completed test runs

Once the tests are complete they are available to view on https://saucelabs.com/jobs. Logs, screenshots and video playback of each test are available for reviewing and investigation.

Rounding Up

This was a very simple overview of setting up SauceLabs, writing and running a very simple cross browser and operating system test and reviewing the results of the tests on the SauceLabs dashboard.

I have not explored the full power of SauceLabs here or how you could save a lot of time by running your tests in parallel. Hopefully this is enough to help get started with SauceLabs. Following the getting started guide on the SauceLabs site is a great way of getting started in the world of cross browser testing in the cloud – http://saucelabs.com/docs/ondemand/getting-started

Posted in Uncategorized | 7 Comments

Working around file upload dialog issues with Selenium 2

One of the most common issues found when using Selenium 2 (and other browser automation tools), is dealing with dialogs, such as alerts and browser upload/downloads. I recently encountered this problem again with a file upload dialog, and I wanted to share my solution.

I use Selenium2/WebDriver to control navigation up to the point where the upload dialog is opened, although any browser automation tool would do the trick. I then execute an AutoIt script to complete the interaction with the dialog. I then run a seperate batch file to kill AutoIt after the dialog has been handled. By looping through these steps, I can process a List of files to be uploaded.


private void uploadAllFilesInBrowser(List<String> filesToBeUploaded) {
try{
	openBrowser();
	goToUploadPage();
	uploadAllFilesInUploadDialog(filesToBeUploaded);
}
finally{
	closeBrowser();
    }
}

private void uploadAllFilesInUploadDialog(List<String> filesToBeUploaded) {
	for(String file : filesToBeUploaded){
		openUploadDialogAndUploadFile(file);
	}
}

private void openUploadDialogAndUploadFile(String filename) {
	openUploadDialog();
        runAutoItFileUpload(filename);	
	killAutoIt();
}

private void runAutoItFileUpload(String filename) {
	Runtime.getRuntime().exec(pathToAutoit + "\\AutoUploadAsset.exe \"" + filename);
}

private void killAutoIt() {
	Runtime.getRuntime().exec("cmd /C start /min " + pathToAutoIt + "\\KillAutoIt.bat");
}

Below is the code for the AutoUploadAsset.au3 file. The AutoIt file, when opened, will enter an infinite loop, waiting for the “File Upload” window to appear. When it does appear, it will enter the filename into the upload field, wait a second, and click the upload button.


While 1
   
	If WinExists("File Upload") then
		ControlSetText('File Upload',"","Edit1", $CmdLine[1])
		
		sleep(1000)
		
		ControlClick('File Upload',"","Button1")
	Endif

   sleep(1000)
Wend

In order for the AutoIt script to be executed in Java with the Runtime.getRuntime().exec() method, it needs to be compiled as an executable. On Windows, right-click on the AU3 file and choose “Compile Script”. An AutoUploadAsset.exe will be created.

Since the AutoIt script is in an infinite loop, we need one final step to kill it, otherwise the same file will be uploaded over and over when the file upload dialog appears. The code below is the KillAutoIt.bat called in the killAutoIt() method.


@echo off
SET root=%~dp0

taskkill /f /fi "IMAGENAME eq AutoUploadAsset.exe"

@echo Killed AutoIt
@echo.
exit

This solution was mostly taken from a similar post at testingexcellence (http://www.testingexcellence.com/how-to-upload-files-using-selenium-and-autoit)

Posted in Test Automation | Tagged , , , , , | Leave a comment

Introduction to Telerik’s WebAii Testing Framework

In this post I will give the briefest of demonstrations of using the WebAii testing framework by showing how to carry out a simple search on google and verify the results – but first, a brief introduction to WebAii.

WebAii is a web automation testing framework, originally developed by ArtOfTest, now provided as a free framework by Telerik. It is similar in idea to other existing browser automation tools such as Selenium, WatiN (even QTP). However, unlike Selenium/WatiN, it is not an open source tool – it is developed and supported by Telerik. The tool is completely free to use – and a paid for version of the product is also available, which offers further functionality, such as the “Test Studio”, which provides test record and playback capabilities amongst other things. However, in this and future posts I will only be talking about the free version of WebAii. This means that there will be no mention of the Test Studio or the record or playback capabilities of the commercial version. All my posts will demonstrate test creation in Visual Studio.

Firstly, installing WebAii is straightforward. It is listed under the free products section on Telerik’s site. After downloading, simply run the msi file, and WebAii will be installed.

Before going any further, I recommend reading the “Configuring your browser” section from the WebAii documentation site. This will ensure that your chosen browser/browsers are ready for use with WebAii.

As mentioned, the first example I want to demonstrate is simply opening google and carrying out a basic search. I will be using Visual Studio and NUnit along with WebAii to demonstrate this.

To get started, create a new C# Library project. Once created, add a reference to “ArtOfTest.Common” and “ArtOfTest.WebAii” which can be found in the WebAii installation directory (in program files). You will also need to reference “nunit.framework” for our unit tests. Finally, use the following code to create our first simple test.


using System.Threading;
using ArtOfTest.WebAii.Controls.HtmlControls;
using ArtOfTest.WebAii.Core;
using NUnit.Framework;

namespace WebAiiTestExamples
{
    public class WebAiiTestExamples
    {
        private Settings mySettings;
        private Manager myManager;

        [SetUp]
        public void SetUp()
        {
            mySettings = new Settings(BrowserType.InternetExplorer, @"c:\log\");
            myManager = new Manager(mySettings);
            myManager.Start();
        }

        [TearDown]
        public void TearDown()
        {
            myManager.Dispose();
        }

        [Test]
        public void SimpleTest()
        {
            myManager.LaunchNewBrowser();
            myManager.ActiveBrowser.NavigateTo("http://www.google.com");
            myManager.ActiveBrowser.Find.ByName("q").Text = "cheese";

            Thread.Sleep(1000);

            myManager.ActiveBrowser.RefreshDomTree();

            Assert.That(myManager.ActiveBrowser.ContainsText("www.cheese.com"), Is.True);
        }
    }
}

The google test can be run directly from Visual Studio using Resharper, TestDriven.Net etc. or directly from NUnit. You should see Internet explorer open, navigate to google, type “cheese” and then a bunch of results appear on the google search results page. Finally, the browser should close. Let’s break down the code above and examine what is happening at each stage.

If you are familiar with NUnit, or testing frameworks in general, then the above test class should be self explanatory. When tests are run, the method decorated with the SetUp attribute will be called first. Anything which needs to happen prior to the tests, such as setting up the environment, should be placed here.

mySettings = new Settings(BrowserType.InternetExplorer, @"c:\log\");
myManager = new Manager(mySettings);
myManager.Start();

In our example, we first create an instance of the Settings class. This is configuration which will be used by the Manager object, as is demonstrated when we instantiate the Manager class on the next line by passing in the Settings instance. As you can see, the Settings class defines the type of browser we want to use in the test, and also the location where WebAii log messages will be logged to. Configuration settings can be provided using this programmatic style or by using configuration specified in a .config file. More information on WebAii configuration can be found on the WebAii Documentation appConfig topic page.

The final line in our setup method is the Manager.Start() method. According to the WebAii 2.0 API reference, this method is used to “Initialize the communication pipelines”. Since we will be reusing our Manager class in all tests (I know there is only one at the moment), this initialisation is carried out in the SetUp method.

Next, any methods with a Test attribute will be run. These are the actual tests which we want to carry out.


myManager.LaunchNewBrowser();
myManager.ActiveBrowser.NavigateTo("http://www.google.com");
myManager.ActiveBrowser.Find.ByName("q").Text = "cheese";

Thread.Sleep(1000);

myManager.ActiveBrowser.RefreshDomTree();

Assert.That(myManager.ActiveBrowser.ContainsText("www.cheese.com"), Is.True);

The first line launches a new instance of the configured browser, in our case, Internet Explorer. The Manager class can actually launch multiple instances of the same browser, or different browsers, however in this example we will only be using a single instance of Internet Explorer. Next, we navigate to google using the active, and only, browser. We then type our search criteria, “cheese”, into the google search textbox.

Lets break down the command on line 3 to understand exactly what is happening with this line of code.

Firstly, we are using the Find property on the active Browser object. The Find class provides methods to search for elements on our Browsers DOM. The are numerous methods available on the Find class, which are well documented in the WebAii Documentation element identification page.

In this example we are using the ByName() method, and providing the “q” parameter, which is the name of the search textbox on google. Also, notice the <HtmlInputText> after the method name. This specifies the TControl type of the elements returned by the Find method. Simply, it provides a wrapper around the the elements, to ensure the appropriate properties and methods are available on the element. For example, it allows access to the Text property on our google search box, but doesn’t provide a Checked property, which would be redundant on a text field.

Finally, we set the text of our input text box to “cheese”.

The next 2 lines of our test are curious, and a few years ago would have been unnecessary. Google now automatically provides search results as soon as you begin to type search criteria using AJAX. As a result, you don’t need to click the search button at all. However, for our test, we will need to give Google time to return our results, hence the Sleep for 1000 milliseconds. This is not an ideal way to deal with AJAX results, and for anything other than our simple demonstration, something more deterministic would be highly recommended. Secondly, we need to inform WebAii that the DOM has actually been updated by the AJAX request, otherwise we will not be able to find the results of the google search. This is done with the RefreshDomTree() method.

Finally, after our search has been completed, we can use the Browser objects ContainsText() method to ensure that our results contain the text “www.cheese.com”. If it does, then our unit test will pass. If it does not, then our unit test will fail.

Finally, the method decorated with the TearDown attribute will be run.


myManager.Dispose();

This should clean up the environment and dispose of anything which created during the SetUp method which needs to be disposed of, in our case, the Manager class.

So, if all has gone well, then you have just seen your first simple WebAii test open google, carry out a search, and verify the results contain what you expect. This is just the tip of the iceberg in terms of WebAii functionality, and in future posts I will further explore the functionality WebAii offers.

Good luck..

Posted in Test Automation | Tagged , , | 3 Comments