Jenkins

Jenkins Build Pipeline Plugin With Manual Retry Build Setup

  • Posted on: 6 September 2014
  • By: Zhijun Chen

Build Pipeline Plugin is very useful in product release process. As the name suggests, You can get a pipeline view of upstream and downstream Jenkins jobs by chaining them together.

The following steps provide plugin setup under Ubuntu system.

  • Install Build Pipeline Plugin

Update Jenkins to the latest version using the following command if needed.

sudo apt-get update
sudo apt-get install jenkins

Navigate to Manage Jenkins -> Manage Plugins -> Available, type "build pipeline plugin", select the plugin and install. Restart Jenkins after installation.

  • Chain Jenkins jobs together

As show in the following picture, I've got three jobs named Release, Test and Deploy.

The sequence would be: Release -> Test -> Deploy. To create the chain, go to each job and specify the following post build actions when applicable.

The following picture gives an example of Test project.

Note: The manual step is required if you would like manual retry button on pipeline to work.

  • Set up pipeline

Create a pipeline view by clicking on the "+" sign next to All tab under Jenkins job view. This will take you to the following screen.

Configure the pipeline to allow manual trigger on pipeline steps and set the initial job.

Save the pipeline view and you should have the following view after a few executions. The retry button on each step should also work.

Selenium WebDriver Parallel Testing with Selenium Grid 2, Jenkins and TestNG

  • Posted on: 17 November 2013
  • By: Zhijun Chen

Recently I've been working on setting up Webdriver parallel testing on a web app. The following guide will give you a brief walkthrough of the steps and technologies.

* WebDriver (Selenium 2.0)

WebDriver is the primary new feature in Selenium 2.0. It aims to better support dynamic web pages where elements of a page may change without the page itself being reloaded. Full documentation of Webdriver can be found here. A useful design pattern in Webdriver is Page Objects, which documentation can be found here. A Page Object simply models web page areas as objects within the test code. Suppose you have a simple login page as shown in the following code.

<html>
  <head>...</head>
  <body>
    <div>Username: </div>
    <div><input type="text" id="username" /></div>
    <div>Password: </div>
    <div><input type="password" id="password" /></div>
    <div><input type="button" id="login_button" value="Login" /></div>
  </body>
</html>

and you would like to model the elements on that page as Java objects.

/* import statements*/

public class LoginPage {
    private By usernameLocator;
    private By passwordLocator;
    private By loginButtonLocator;
    private final WebDriver driver;

    public LoginPage(WebDriver driver) {
        this.driver = driver;
        initLocators();
    }
    
    private void initLocators() {
       usernameLocator = By.id("username");
       passwordLocator = By.id("password");
       loginButtonLocator = By.id("login_button");
    }
    
    public LoginPage setUsername(String username) {
        WebElement usernameEl = driver.findElement(usernameLocator);
        usernameEl.clear();
        usernameEl.sendKeys(username);
        return this;
    }
    
    public LoginPage setPassword(String password) {
        WebElement passwordEl = driver.findElement(passwordLocator);
        passwordEl.clear();
        passwordEl.sendKeys(password);
        return this;
    }
 
    public HomePage clickLoginButton() {
        driver.findElement(loginButtonLocator).click();
        // Return a new page object representing the destination
        return new HomaPage(driver);
    }
}

The page object class should only be responsible for elements on the page. All assertions should be made inside the tests. A simple login test can then be written as follows.

public void testLogin() {
   LoginPage loginPage = new LoginPage(driver);
   loginPage.setUsername("username");
   loginPage.setPassword("password");
   loginPage.clickLoginButton();
   // some assertions here, e.g. Home page title
}

To improve stability of selenium tests, it is necessary to add WebDriverWait when using WebDriver.findElement method. You also need to make sure that the element is scrolled into view before you interact with it. This can be done through JavascriptExecutor in WebDriver.

((JavascriptExecutor) driver).executeScript("arguments[0]".scrollIntoView(true), element);

It's also helpful to catch StaleElementReferenceException and re-initialize the element.

* Selenium Grid 2

Selenium Grid facilitates Selenium tests by allowing users to:

  • scale by distributing tests on several machines
  • manager multiple environments from a central point, making it easy to run the tests against a vast combination of browsers/operation systems.
  • implement custom hooks to leverage virtual infrastructure for instance.

The following diagram shows the idea of Selenium Grid 2.

 

Here are the steps to set up the grid:

  • Download Selenium Grid standalone server from here.
  • Start Selenium Grid Server using the following command, by default the server will run on port 4444, you can have a look at the grid console on http://localhost:4444/grid/console
java -jar selenium-server-standalone-$version.jar -role hub
  • Register nodes using the following command. Note: For chrome you need to download ChromeDriver, and for IE you need to download IEDriverServer.
java -jar selenium-server-standalone-$version.jar -Dwebdriver.chrome.driver=$chromedriver_location -Dwebdriver.ie.driver=$iedriver_location -role node -hub http://localhost:4444/grid/register

More information can be found here

After setting up the grid, you can now use RemoteWebDriver instead in your Selenium code as follows.

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setBrowserName("firefox");
capabilities.setPlatform(Platform.MAC);
// disable native event
capabilities.setEnableNativeEvents(false);
RemoteWebDriver driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), capabilities);

When running Selenium tests under multiple browsers in the same machine, there will be browser focus issues. This will lead to test failures. Setting native vent to false will help in this case.

Alternatively, there are some decent Selenium cloud testing platforms available. One of them is Sauce Labs. They allow you to run Selenium tests on the cloud, and test on all possible browser/OS combinations, without having to install them on a local machine. Free plan is also available.

* TestNG

Integrating TestNG into Selenium tests is pretty straightforward. The main advantages of TestNG are parallel tests execution and the use of parameters. Most of the assertions and annotations are quite similar to JUnit. Information can be found here. One way to implement parallel testing in Selenium is to set browser and system as parameters as shown in the following code.

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="TestSuite" parallel="tests" thread-count="5"
  verbose="1">
  <test name="mac-chrome">
    <parameter name="browser" value="chrome" />
    <parameter name="platform" value="mac" />
    <classes>
      <class name="uk.co.zhijun.SeleniumTest" />
    </classes>
  </test>
  <test name="windows-chrome">
    <parameter name="browser" value="chrome" />
    <parameter name="platform" value="windows" />
    <classes>
      <class name="uk.co.zhijun.SeleniumTest" />
    </classes>
  </test>
</suite>

The attribute parallel="tests" allows us to run same tests at the same time but using different parameters. The browser and platform can now pass in to the capability method as follows.

@Parameters({"browser", "platform"})
@BeforeClass
public DesiredCapabilities getCapabilities(String browser, String platform) {
   // code to initialize capabilities
}
* Jenkins

Two useful plugins can be used inside Jenkins to publish Selenium tests report.

It's very easy to set up, you just need to pass in the testng-results.xml file as the input. For Performance plugin, you can even pass in different result xml files generated under different browsers and systems.

Set up Git and Jenkins under Ubuntu

  • Posted on: 26 January 2013
  • By: Zhijun Chen
* Install Git and set up Git

Git is a distributed version control system and can be installed using the following one command:

sudo apt-get install git

After it finishes downloading, you will have Git installed and ready to use. Use the following commands to config global username and email.

git config --global user.name "username"
git config --global user.email "email"

Use the following command to see all of your settings:

git config --list
* Set up a new Git project

After installing Git, you should be able to create a new Git project.

There are two types of repositories in Git: development repository and bare repository. A development repository is used for normal, daily development, e.g. editing, adding and deleting files. In contrast, a bare repository has no working directory and it serves as an authoritative basis for collaborative development. You can pull/push changes from/to bare repositories.

Use the following commands to set up a remote bare repository

ssh git@example.com  
mkdir my_test_project.git 
cd my_test_project.git 
git init --bare

After setting up bare repository, we need to init a local project and do a initial "push" to the bare repository. So on local machine, do the following:

cd my_test_project
git init
git add * 
git commit -m "Initial commit message" 
# Add remote origin, specify your own project path 
git remote add origin git@example.com:my_test_project.git
git push -u origin master

Others can clone the remote repository using the following command

git clone git@example.com:my_test_project.git
* Install Jenkins

Install Jenkins using the following command:

wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins

For more configurations, please refer to Installing Jenkins on Ubuntu

* Install Jenkins Git plugin

After installing Jenkins, you should be able to access Jenkins root page at http://your_jenkins_host:8080/

Next we should install Jenkins Git plugin to allow Jenkins to talk to Git repository. If your Jenkins instance has security enabled, login as a user who has the Overall/Administer permission.

Select Manage Jenkins link on the left-hand side of the screen. Click on Manage Plugins link.

Under Available tab search for "git" then you should be able to select the Git plugin.

Click the Download now and Install after restart button at the bottom.

* Configure job in Jenkins

Navigate to Jenkins instance job or create one if none exists.

Select Configure link on the left hand side of the screen In the Source Code Management select Git option and enter the previous git address which looks like ssh://git@example.com/my_test_project.git. Note: Make sure that the bare git repository is visible to Jenkins otherwise errors would be thrown.

For more information please refer to Jenkins Git Plugin Click Save button at the bottom.

* Configure Jenkins to build automatically after Git push

You may want to trigger Jenkins job to build automatically after each Git push. You can achieve this simply by using Git post-receive hook.

To do this, navigate to job configuration page by clicking on Configure link on the left hand side. Check Poll SCM option under Builder Triggers.

In the machine which holds Git bare repository, inside my_test_project.git folder, go into hooks folder and create a file called post-receive, and type in the following command:

curl http://your_jenkins_host:8080/git/notifyCommit?url=path_to_bare_repository

for instance, curl http://localhost:8080/git/notifyCommit?url=/Projects/myproject.git

Go to your Git development repository and do a Git push, you should see the following message.

"remote: Scheduled polling of my test project"