Neosavvy, Inc Modern Knowledge Blog

5May/102

Getting RIA Test / Maven / Flex Mojos to play nice

What is RIA Test

This tool is a for pay click test tool that records and plays back automated click tests. It can help streamline the testing process and reduce testing costs via automation and reduced numbers of QA team members.

See more here

Why should you read this article?

This article is relevant to you if you are using Flex Mojos to build your code and are interested in automated click testing. When I first attempted to setup RIA Test I noticed that the instructions lacked information about how to make it work for users who use ANT or Maven to build their code, likely because they don’t know that it is common practice to do so.

Assumptions

  1. You have a build process in Maven for your flex applications
  2. You are using Flex Mojos for the actual compilation process
  3. RIA Test is your desired agent for testing
  4. You are using a repository manager like Nexus for the Maven repository
  5. You are using Flex 3.4 or 3.5

Step 1 – Add necessary dependencies to Nexus

The automation libraries are required to embed and run the agent to record and playback the test scripts. You can find them on Adobe’s site here:

Flex 3.5: http://download.macromedia.com/pub/flex/sdk/automation_sdk3.5.zip

Flex 3.4: http://download.macromedia.com/pub/flex/sdk/automation_sdk3.4.zip

I was unable to locate any older libraries.

Unzip the files so that the folder structure looks like this:

Automation Directory Structure

All of these files except the ja_JP files need to be uploaded to your nexus repository. I will not cover that here but I have pasted the POM entries for how I uploaded my 3.5 libraries.

     <dependency>
                <groupId>com.riatest</groupId>
                <artifactId>riatestagent</artifactId>
                <version>3</version>
                <type>swc</type>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.adobe.flex.framework</groupId>
                <artifactId>automation_rb</artifactId>
                <version>${flex.version}</version>
                <type>swc</type>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.adobe.flex.framework</groupId>
                <artifactId>automation_agent_rb</artifactId>
                <version>${flex.version}</version>
                <type>swc</type>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.adobe.flex.framework</groupId>
                <artifactId>automation</artifactId>
                <version>${flex.version}</version>
                <type>swc</type>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.adobe.flex.framework</groupId>
                <artifactId>automation_agent</artifactId>
                <version>${flex.version}</version>
                <type>swc</type>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.adobe.flex.framework</groupId>
                <artifactId>automation_dmv</artifactId>
                <version>${flex.version}</version>
                <type>swc</type>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.adobe.flex.framework</groupId>
                <artifactId>qtp</artifactId>
                <version>${flex.version}</version>
                <type>swc</type>
                <scope>test</scope>
            </dependency>

Step 2 – Add the dependencies to your pom.xml

Great now assuming you have them added to your repository, you can reuse that pom.xml section from above and place it in your top level pom file for your flex projects in the dependencyManagement section to ensure all children inherit the dependency.

Step 3 – Upgrade to Flex Mojos 3.6.1

This step could be problematic but it is relatively simple to test. First you will just need to locate your plugin configuration or the variable that controls what version of Flex Mojos you are using. You then need to change it from 3.4.0 to 3.6.1.

When I made this change I was using custom gas3 code generation and depended on graniteds1. I found some help here: https://docs.sonatype.org/display/FLEXMOJOS/Generator+Mojo#GeneratorMojo-flexmojos36

The main gist of it is that you need to have a separate plugin used for generation so you can override the default graniteds dependencies in 3.6.1. If you don’t use graniteds generation, then you won’t have to worry about this problem, but you could run into others. Please post in the comments if you have an issue as it would be great for others to benefit from your fix.

Step 4 – Compile the test swc

After the dependencies are set you should be able to run

mvn clean install flexmojos:test-swf

on the project that you would like to create record playback scripts in. You will see a new artifact in the target directory with the word “test” as the classifier and you can then run that to connect to the RIA Test IDE.

Thanks for reading, I hope this short how-to is helpful and saves time for someone as I spent a few extra hours making this work in my scenario.

Cheers!

21Mar/102

Continuous Integration with Jetty/Cargo/Maven/Bamboo

Recently I have had the pleasure of helping migrate a client to a maven build process where they wanted to also migrate to a Jetty container from a full blown JBoss application server. The decision to move to Jetty is probably wise as they don’t need all of the extras provided by JBoss as they aren’t really using all of them.

Regardless this move presented an interesting hurdle. One of the requirements that dictated success of the migration was successful remote deployment from a Bamboo continuous integration build environment on a windows server to a remotely deployed Jetty instance. The main crux of this setup is that Jetty does not support remote deployment natively. Also I chose to configure cargo’s remote deployer to handle the deployment in a push fashion. Luckily a kind person at Redhat has written a cargo remote deployer that can be deployed as a war file to the Jetty server. This deployer then allows the cargo maven plugin to push a file. The cargo hook however does not support the removal of the previously deployed artifact, so in a continuous integration environment trying to support a push button deploy won’t work – one has to cleanup after themselves.

Out solution was to use some functionality from JCSH to make a java client that can call a script on the Jetty server to delete the old artifact and restart the application server. The code to handle the remote call can be seen below and is admittedly hackish but definitely solved my problem in a few hours where I wasn’t necessarily granted the permission of infinite time to solve this problem.

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
66
67
68
69
70
71
72
73
74
75
76
77
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
 
import java.io.*;
 
public class RebootJetty {
 
    private static String DISC_STRING = "###### SERVER CLEANED #####";
 
 
    private static String TEST_QA = "10.0.0.1";
    private static String TEST_QA_PASSWORD = "password!";
 
    private static String APP_QA_1 = "10.0.0.2"; 
    private static String APP_QA_1_PASSWORD = "password2";
 
    public static void main(String[] args) throws Exception {
        com.jcraft.jsch.JSch jsh = new JSch();
 
        Session testSession = jsh.getSession("root", APP_QA_1 , 22);
        testSession.setConfig("StrictHostKeyChecking", "no");
        testSession.setUserInfo(new MyUserInfo());
        testSession.connect(10000);
 
        Channel channel = testSession.openChannel("shell");
        channel.setInputStream(new StringBufferInputStream("/root/cleanupJetty.sh\n"));
        channel.connect();
 
        PipedOutputStream pos = new PipedOutputStream();
        channel.setOutputStream(pos);
        PipedInputStream pis = new PipedInputStream(pos);
 
        BufferedReader r = new BufferedReader(new InputStreamReader(pis));
        String s = "";
        while (s != null) {
            s = r.readLine();
            System.out.println(s);
            if (s != null && s.indexOf(DISC_STRING) > -1) {
                channel.disconnect();
                System.exit(0);
            }
        }
 
        System.exit(1);
 
    }
 
    public static class MyUserInfo implements UserInfo {
 
        public String getPassphrase() {
            return APP_QA_1_PASSWORD;
        }
 
        public String getPassword() {
            return APP_QA_1_PASSWORD;
        }
 
        public boolean promptPassphrase(String arg0) {
            return false;
        }
 
        public boolean promptPassword(String arg0) {
            return true;
        }
 
        public boolean promptYesNo(String arg0) {
            return false;
        }
 
        public void showMessage(String arg0) {
 
        }
 
    }
}

The Maven Cargo Plugin however was extremely helpful and was not extremely hard to configure however it doesn’t support all features equivalently in all application servers. Make sure to check your application server on their feature matrix for the scenario you are attempting to see if it even works out of the box. In my case they even advertise that it works, but after reading their Jira issues I noticed it is fixed in an alpha release of their plugin but advertised as working in their latest release…frustrating…

Cargo Feature Matrix for Jetty 6.x: http://cargo.codehaus.org/Jetty+6.x

You will need to make sure to download and build the war file to deploy to your target Jetty to support remote deployment. I found it here: http://svn.codehaus.org/cargo/resources/trunk/jetty-deployer/

To make the code above work I downloaded their entire trunk and built it locally, then I modified their war file to remove security settings so I wouldn’t have to setup a security realm in Jetty. Not sure how hard that really is, but given this is an internal continuous integration server I didn’t really care about deployment security as Bamboo would only allow secure uses to click the button to cause the deployment to occur. Other than that one of the 8 developers on the team would have to execute the maven profile to cause a deployment, and likely if one of them does it, then it probably needed to happen. Specifically the code I commented out was in here: http://svn.codehaus.org/cargo/resources/trunk/jetty-deployer/src/main/webapp/WEB-INF/web.xml I removed the login-constraint and the security-constraint.

Here is the code required to push a release to a remote running server instance. Just throw this in a profile in your pom or add the plugin to your build section if you prefer it run in your pom. I opted to use a profile so that I can enable it as necessary and others can use this same pom to build the WAR for normal use. There is another profile in use for a local deployment to Jetty which is way easier with cargo.

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
        <profile>
            <id>deploy-to-qa</id>
            <build>
                <plugins>
 
                    <plugin>
                        <groupId>org.codehaus.cargo</groupId>
                        <artifactId>cargo-maven2-plugin</artifactId>
                        <version>1.0.1-alpha-1</version>
 
                        <configuration>
                            <container>
                                <containerId>jetty6x</containerId>
                                <type>remote</type>
                                <timeout>120000</timeout>
                            </container>
 
                            <configuration>
                                <type>runtime</type>
                                <properties>
                                    <cargo.hostname>172.1.0.1</cargo.hostname>
                                    <cargo.servlet.port>80</cargo.servlet.port>
                                    <cargo.remote.username>user</cargo.remote.username>
                                    <cargo.remote.password>pass</cargo.remote.password>
                                </properties>
                            </configuration>
 
                            <deployer>
                                <type>remote</type>
                                <deployables>
                                    <deployable>
                                        <groupId>${project.groupId}</groupId>
                                        <artifactId>${project.artifactId}</artifactId>
                                        <type>war</type>
                                    </deployable>
                                </deployables>
                            </deployer>
                        </configuration>
 
                    </plugin>
 
                </plugins>
            </build>
        </profile>

The final piece to the puzzle is likely the cleanupJetty.sh script that resides on the target server. This script simply stops jetty, deletes the war file deployed by cargo, then starts jetty again. It is called via a call into the JSCH program above from the windows box via command line (in Bamboo) and then after it completes it kicks off the maven build. Here is the contents of the script:

1
2
3
4
5
6
#!/bin/bash
/opt/jetty/bin/jetty.sh stop
rm -rf /opt/jetty/webapps/NAME_OF_WAR
/opt/jetty/bin/jetty.sh start
sleep 20s
echo "###### SERVER CLEANED #####"

I sure hope this little tidbit helps someone out there as I did a lot of reading on forums and Jira bugs to figure out how to make this all work. If you have a similar setup please let me know as I am happy to help you out. Also please note that I will openly admit that the JCSH hook from a windows box into the bash script could arguably be considered a hack, but sometimes it just has to work.

30Aug/091

Neosavvy’s Neverending Quest to Improve Code Quality

My name is Adam Parrish and I have been spending a large portion of my free time working on a project called SVN Analytics or SVN Spy. The goal of my extracurricular effort is to create an open source alternative for the Fisheye toolset and potentially answer some of the questions that Fisheye helps developers answer. As a result of this effort another goal has emerged in search of a method of creating greater code quality.

In search of greater code quality, it is important to factor in the following concepts:

1) Version control
2) Continuous Integration
3) Judicious and constant refactoring
4) Proper organization in project management

The above concepts may seem obvious, but in an attempt to grow personal knowledge and share with others this blog will become a log of a journey exploring software engineering and forming good habits that improve the lives of software craftsman.

Neosavvy is a company that will be built around the desire to grow good habits in software engineering process and share this "modern knowledge" with other like minded software craftsman.

   

Pages

Categories

Blogroll

Archive

Meta