Category Archives: Programming

Spring Boot, Docker integration with IntelliJ and Windows

In this post I’ll give a more detailed guide for the Spring Boot and Docker initiative.

The final goal that I had in mind, was to have a Docker container that runs the packaged java application in a clean environment.
Support for remote debugging is included in the configuration, as well with both running and debug listening ports mapped/forwarded between the windows and docker machine. So in the end you can access the application as if it was running on your “localhost” 😀

Pre-requisites:
– Docker ToolBox for Windows (with VirtuaBox) Dowload link
– A Spring Boot or any Java project with Maven support will suite the purpose Getting Started with Spring Boot
– IntelliJ Docker plugin installed

After installing the Docker Toolbox (next > next > next…) we can jump right into creating a simple HelloWorld Spring Boot Web Starter project.
To do this in the fastest way, create a New Project > Maven and inside the pom.xml add the following dependency:

1
2
3
4
5
6
7
8
9
10
11
12
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>

   <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

Next, add a “hello” package and a java class that will act as our Rest Controller (HelloController.java) in which we map the default “/” context path to a method that returns a default “Hello” String.

1
2
3
4
5
6
7
8
9
@RestController
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "This is Spring Boot with Docker!!";
    }

}

Create another class, with a main method that will be the entry-point to our application. The @SpringBootApplication makes everything smooth :)

1
2
3
4
5
6
7
8
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

This is my trimmed version of the “Getting Started with Spring Boot” from the official site.
You can go ahead and run “mvn package” command to generate the application’s executable .jar file.

Now for the Docker part, let’s start with installing the IntelliJ “Docker integration” plugin. This offers easier communication with the docker and saves some time, cause you won’t have to spam “docker build” … “docker run” commands in a separate console.

In the Maven pom.xml file, you’ll need to add the following docker-maven-plugin along with a few very important configuration lines.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.5</version>
                <configuration>
                    <dockerHost>https://192.168.99.100:2376</dockerHost>
                    <imageName>spring</imageName>
                    <baseImage>java</baseImage>
                    <env>
                        <server.port>8888</server.port>
                        <java.security.egd>file:/dev/./urandom</java.security.egd>
                    </env>
                    <exposes>
                        <expose>8888</expose>
                        <expose>5005</expose>
                    </exposes>
                    <entryPoint>["java", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005", "-jar", "/${project.build.finalName}.jar"]
                    </entryPoint>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>

In the configuration we are able to specify the baseImage and imageName along with the expose and entrypoint parameters which are very common in a Dockerfile. In our case, we won’t be needing one at all, because the maven plugin will do all the work for us!

The environment variables are used to specify the server.port to run on 8888 instead of the default 8080 (yes, I’m still using Skype…)
The ports also need to be exposed from the docker container so both the server and remote debugging ports are added.
Entrypoint is basically the whole java command used to run the server, in our case the resulting “.jar” file after mvn package. It contains some extra arguments to enable remote debugging for the server.

In order to make use of this plugin we need to run “docker:build” from maven/plugins section.

Docker Build mvn
After it’s finished we will have a new “spring” image derived from the default Java one. Now here comes the Docker and IntelliJ integration part.

Docker plugin

We will go ahead and create a new Docker Deployment configuration as follows.
Docker Run configuration

We can then press Play and our container will be started along with the application server. In order to be able to access the server from Windows, we need to forward the 8888 and 5005 port respectively, from the docker machine to running Windows OS (this isn’t necessary if you’re a Linux guy, because the docker-host is running natively).

To do this we can use the following commands from an “elevated windows command prompt” (just run it as Administrator):

1
2
netsh interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=8888 connectaddress=192.168.99.100 connectport=8888
netsh interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=5005 connectaddress=192.168.99.100 connectport=5005

Everything is set and we can now access our application deployed inside the docker container from windows: http://localhost:8888

You can find the code here: SpringDocker Project

Hope you enjoyed this tutorial,
-M.

Soap WebService testing using Stub generation

In this tutorial I will show an easy way on how to generate Stubs needed to call SOAP webservice methods from Java (or in this tutorial, with Groovy).

The SOAP webservice that I have in mind for this demo is the free Global Weather WebService and we will be needing its WSDL:

1
http://www.webservicex.net/globalweather.asmx?WSDL

Will now go ahead and create a new Maven project in IntelliJ IDEA 15 and then Add Framework Support and select check the Webservice client.
You can also find a link to the GitHub project at the end of this post.

Before generating the stubs, we need a few dependencies to be added in the pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<dependencies>
        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>axis</groupId>
            <artifactId>axis-wsdl4j</artifactId>
            <version>1.5.1</version>
        </dependency>

        <dependency>
            <groupId>axis</groupId>
            <artifactId>axis-jaxrpc</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>commons-discovery</groupId>
            <artifactId>commons-discovery</artifactId>
            <version>0.5</version>
        </dependency>

        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.4.5</version>
        </dependency>
    </dependencies>

What we need to do now is right click on a folder in our project and select the last option WebServices -> Generate Java Code from Wsdl

IDEA

After the Stub generation is finished, we will find the following files inside the stubs package

IDEA Project Structure

We are aiming to be able to call the methods of the global webservice:

1
2
public String getWeather(String cityName, String countryName)
public String getCitiesByCountry(String countryName)

but in order to do that, we need to get ourselves an instance of the GlobalWeatherLocator and furthermore, access the GlobalWeatherSoap_PortType object which has the 2 methods that we’re interested in.
A quick note here: Don’t be fooled by the “String” return type of these 2 methods, the String is actually … XML so we’re going to need a XmlSlurper to parse it and perform asserts.

Using Groovy, this code will look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
import stubs.GlobalWeather
import stubs.GlobalWeatherLocator
import stubs.GlobalWeatherSoap_PortType


GlobalWeather globalWeather = new GlobalWeatherLocator()
GlobalWeatherSoap_PortType globalWeatherSoap = globalWeather.getGlobalWeatherSoap()

def xmlResponse = globalWeatherSoap.getWeather("Bucuresti", "Romania")

def parsedXML = new XmlSlurper().parseText(xmlResponse)
assert parsedXML.Status == "Success"

The code for the project can be found on GitHub – WebServiceClientStubs

Hope you’ve enjoyed generating some stubs.

Selenium DDT with TestNG and DataProvider

Hi there,

Of course there are many ways to do Data Driven Testing but if you’re familiar with Java or OOP in general you’re going to like this approach with TestNG and DataProvider.

First let’s give a short intro to @DataProvider; this annotation will require a name and holds a method that returns either an Object[][] or an Interator

For the scope of this article, we will try to login multiple times on a particular site, such as gmail.com with the username and password combinations provided in an “input.txt” file:


1
2
3
user1, pass1;
user2, pass2;
user3, pass3;

Now let’s see the code for our custom readText() method and review it based on the particularities of the above input.txt file:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public static Object[][] readFile(File file) throws IOException {
        String text = FileUtils.readFileToString(file);
        String[] row = text.split(";");

        int rowNum = row.length;
        int colNum = row[0].split(",").length;

        Object[][] data = new String[rowNum][colNum];

        for (int i = 0; i &lt; rowNum; i++) {
            String[] cols = row[i].split(",");
            for (int j = 0; j &lt; colNum; j++) {
                data[i][j] = cols[j].trim();
                System.out.println("The value is " + cols[j].trim());
            }
        }
        return data;
    }

So as you can see, we’ll be passing 1 argument to our readText() method, the “file” that needs to be read. We’re then using the Apache Commons IO, FileUtils library to read our .txt file so make sure you have that imported (seems that our “custom” readText() method is not so custom afterall :) )

We’re storing all the read content inside a string and then we’re going to do a split (a fabulous one) by the semicolon (“;”) character since that seems to be separating each individual row.

Now to find out the number of “columns” we can do another split by the comma character (“,”) since it is separating each username by its password. Of course you can use any other character for separation and then do a split by it (i.e. a pipe | or a tilda `  or anything else).

Next step will create an array of array of Objects called “data” and it will have the size of data[rows][columns] that we obtained earlier.

What’s left next is to make 2 for loops in order to iterate through the number of rows and then columns while assigning the read value to the data[][] array without the whitespaces, which will be trimmed.

In the end our method will return the “data” Object[][].

So we’re now going to use this method for the @DataProvider annotation:


1
2
3
4
5
6
7
@DataProvider(name = "text")
    public static Object[][] readFile() throws IOException {
        File file = new File("input.txt");
        ReadText txt = new ReadText();
        Object[][] returnObjArray=txt.readFile(file);
        return returnObjArray;
    }

What’s left to do is to pass this @DataProvider to a @Test method that makes use of its 2 parameters and since we said we’re going to try to login to gmail we’re gonna do just that:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 @Test (dataProvider = "text")
    public void loginGmail(String user, String pass) {
        driver = new FirefoxDriver();

        driver.manage().timeouts().implicitlyWait(7, TimeUnit.SECONDS);
        driver.get("http://www.gmail.com");
        WebElement username = driver.findElement(By.id("Email"));
        username.sendKeys(user);

        WebElement password = driver.findElement(By.id("Passwd"));
        password.sendKeys(pass);

        WebElement loginButton = driver.findElement(By.id("signIn"));
        loginButton.click();

        Assert.assertTrue(driver.findElement(By.cssSelector("a[title*='Inbox']")).isDisplayed());
    }

Notice how the dataProvider name in the @Test annotation corresponds with the name of the @DataProvider and how the test method “loginGmail” accepts 2 String arguments which corresponds with a row of parameters from our input.txt file

In the end our test will be executed 3 times because there are 3 rows of username+password combinations which are passed from file.

Enjoy DDT,

-M.

Table doubling + hash tables = love

Hello reader,

During my quest for learning I have encountered this thing, the “Table doubling”. Boy I was so happy about it that I wrote this article :).

The goal is to structure some data, any data, in such a way that we can delete, insert and retrieve really really fast while having a decent memory usage. A real life example would be the HTML code of a webpage. If we consider each HTML element (node) with its properties a set of data we want to get the one that we care about super fast, not in a second or so. So, in order to get a sense of why this is useful I will lay down some premises.

An array = a linear piece of memory of the length of the array. This will be always busy. The array must have the keys/indexes integers. We can’t have the key/index 2.3 or 0.1. Due to those two properties we can get to any element almost instantly because it exists and we know where it is exactly.

A linked list = A piece of data that besides its “internal” information that we care about (for our example let’s say the inner text), it has a link to location in the device’s memory for the next item after it. So 1 knows where 2 is, 2 knows where 3 is, so on and so forth. This is rather sweet but if goes only forward, with a bit of extra work we get to double linked list.

Double linked list = a linked list where the individual piece of information knows about the previous piece as well as the next. Although it has a bigger footprint it solves our previous request in a neat fast way.

Now, in order to nail down the difference, let’s look at what happens when we want to add an element close to the beginning of an array and of a list (double or linked, it doesn’t matter).

Operation Array List
Fetch an element by key
aka
Exact search
Go to key’s position Go to the first or last
Check if it is the one we need
If not ask where the next or previous is located
Repeat the previous two steps until found it*
Insert Increase the length of the array with a number of elements equal with how many we will insert
Move to the right all the other elements in a descending order
Add our data where we wanted to **
It will go at the end of the list and it will tell the last element to have it’s memory address stored.
Delete Remove the element
Move all the other elements to the left
Decrease the size of the array
Go to the desired element forwards or backwards
Tell the element to the left to point to the element to the right. If needed tell the element to the right
to point to the left one

* In case it is not obvious how slow it is. Take a piece of paper and write the steps for finding the 5th element and count the rows.
** It will not put it at the end of the array because the order matters. The premises was that we are close to the beginning of the array so don’t think of adding at the end.

In conclusion, as we can see, there are quite some advantages and disadvantages for each of the data types.

Now in order to find the holly ground of those two data types we will discover a new one, called Hash Table. The not so official definition would be an array that stores as values of its keys pointers to – in the worst case scenario – lists of data with all its properties.

The other concept of this post is Table doubling . This says in less words that instead of resizing an array 1 element at a time, when it gets filled we make it twice as long as it is now. This will allow us to hold twice as much data for future inserts after one operation, and eliminates the need of moving all the elements all the time. The second part is that on delete we shrink it by at least 1/3. This means that inserting and deleting a few elements will not trigger the resizing.

Let’s look at every operation and see the advantage.

Exact search:
Now due to being an array we get very fast navigation and finding.
Insert:
From time to time it triggers the array re-hashing but not so often. As long as we play with the same amount of data or fiddle a bit with the “1/3” value mentioned earlier, everything will work with the speed of the list.
Delete:
The deletion takes part only where there are a lot of free elements, and event after the deletion we have room for more than we had in the beginning. Almost as fast as the double linked list.

 

Conclusion:
I can see this saving seconds on every test case ran on a page with a few hundredth elements.

Assign the same tests to the Zephyr suites after they are moved to another project

Hello,

We have received the task of copying a very big suite of tests from a project to another and maintain their test cycle assignment. For the copy and moving part is easy, there are bulk actions. For the automatic assignment we couldn’t find a quick solution, probably there was.

 

Here’s our approach:

1) On the Test Cycles page we extend a test cycle that has tests which will be moved. This is necessary in order to figure out which to move.

In the browser’s console we run this code (search for domain in the ajax call and replace with your own domain):


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
(function($) {
    var cycleId = (function() {
            var el = $('li.expanded');
            return el.length &gt; 0 ? el.attr('id').replace("cycle-","") : false;
        })(),
        projectId = (function() {
            var el = $('#zprojectId');
            return el.length &gt; 0 ? el.attr('value') : false;
        })(),
        pageCount = (function() {
            var pageText = $('#getMoreSchedulesLbl').text(),
                count = pageText.match(/[0-9]{1,3}/g);
            return Math.ceil(count[count.length-1]/10);
        })(),
        i = 1,
        responses= [],
        offset,
        completed = 0;
    $('body').on('requestscompleted', function(){
        var len = responses.length,
            i = 0,
            summary = [],
            response;
        for(i; i &lt; len; i++) { // iterate through all received responses
            response = responses[i];
            console.log(response);
            (function(item){
                var i = 0,
                    schedules, len;
                if(typeof item != 'undefined') {
                    schedules = item.schedules,
                        len = schedules.length;
                    for(i; i &lt; len; i++) {
                        summary.push(schedules[i].summary);
                    }
                }
            })(response);
            console.log(summary);
        }
    });
    if(cycleId &amp;&amp; projectId) {
        for(i; i &lt;= pageCount; i++) {
            if(i == pageCount){
                lastPage = $('#getMoreSchedulesLbl').text().match(/[0-9]{1,3}/g);
                offset = (lastPage[lastPage.length-1] - ((i-1) * 10));
                console.log(offset);
            }else{
                offset = i * 10;
            }
            $.ajax('domain/rest/zephyr/latest/schedule?decorator=none&amp;contentOnly=true&amp;noTitle=true&amp;cycleId=' + cycleId + '&amp;action=expand&amp;offset=' + offset + "&amp;pid=" + projectId + "&amp;vid=-1&amp;sorter=ID", {
                method: "GET",
                async: false,
                complete: function(){
                    if(completed == pageCount -1) {
                        $('body').trigger('requestscompleted');
                    }
                    completed++;
                },
                success: function (response){
                    responses.push(response);
                }
            });
        }
    }
})(jQuery);

 

2) This returns an array of test names. Those names will be used as identifiers later on. Please copy them into another external document.

3) Copy or move the tests into the other project as desired

4) Open the tests search page on the new project and display as many as possible (the current functionality does not cycle through the pages)

5) Paste the following code and replace the first line with the array exported by the previous code:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var incomingTitles = ["[Event Validation] Frontend - Checkout flow", "[Event Validation] Frontend - Mobile site", "test name 2", "test name 3", "test name 1", "test name 2", "test name 3", "test name 1", "test name 2", "test name 3", "test name 1", "test name 2", "test name 3", "test name 1", "test name 2", "test name 3", "test name 1", "test name 2", "test name 3", "test name 2", "test name 3", "test name 1", "test name 2", "test name 3", "test name 1", "test name 2", "test name 3", "test name 1", "test name 2"];

(function($,incomingTitles){
    var testSummary = (function(){
        var summaries = $('td.summary'),
            i=0,
            title="",
            currentItem = '',
            currentItemVal = '',
            keysHolder = new Array();
        summaries.each(function(){
            currentItem = $(this).find('a.issue-link').text();
            currentItemVal = $(this).find('a.issue-link').attr('data-issue-key');
            //console.log(currentItem);
            if(incomingTitles.indexOf(currentItem) != -1){
                keysHolder.push(currentItemVal);
            }
        });
        console.log(keysHolder);
        return keysHolder;
    })();
})(jQuery,incomingTitles)

This function will export an array of test IDs. Copy them in a document.

6) Open the “Plan Test Cycle” page and click the cogwheel to add tests

7) Paste the array of IDs returned by the second script

 

We have tried to use the filters functionality but we could not select only the tests assigned to a suite. It got even worse when the same tests were assigned to more widgets.

Thank you,

Gabi