2011-12-21

lwp-request or GET and POST and self signed SSL certificates (HTTPS)

I was using the command line last night when I needed to hit one of my pages real quick. I didn't need the output all browser fancy, and I just needed a blurb of text, so I typed GET and the page address plus my credentials. I received an error from down in the bowels of Perl and the LWP::UserAgent library about my certificate not being verified.

I looked around the Internet, and I saw different posts, but nothing told me exactly what to do. Different peoples solutions were vastly different. So, I looked for the documentation for the LWP libraries, and I found them. There I found the exact solution. The library can be affected by environment variables. The specific one is PERL_LWP_SSL_VERIFY_HOSTNAME. It is a boolean value or 0/1 in Perl. So on the command line I simply ran:

export PERL_LWP_SSL_VERIFY_HOSTNAME=0

I then reran GET, and everything was good. So, if you run into this problem, then here is your fix. Simple and sweet.

2011-04-13

Automated Web Testing with Selenium and The NetBeans Rich Client Platform

I developed tooling for work I do for Scripps which helps me create Selenium based automated user tests more easily. These are not open source at this time, though that may be possible some day. I might use the ones I have created as an example to make some better for OSS since I have learned lessons along the way.

This tooling has been built on the NetBeans Rich Client Platform, but too, will run right in the IDE. I show IDE examples in this post. It helps create Java projects for using Selenium for automated user testing. This ties in nicely with the IDE.

There are different technologies supported in the tooling. There is a JavaScript runner or window which allows one to run JavaScript inside Selenium using runScript and getEval. Too, there is project support for Java and Groovy. I don't show the Groovy support here, but it is exactly the same as the Java examples less you will be using a Groovy file instead of a Java file, so you can derive how it works from that.

This is not the same as the tooling available in the current NetBeans auto update centers. I noticed it when I started this, and I don't see that it addresses things in the same manner which I do. I don't focus on the tests in this case as much as I focus on being able to test chunks of code as you are trying to develop the logic which will exercise your application.

The reason I do this is because I do not just write tests. I create automation APIs which can be used to affect the system. This then allows tests to be created using those APIs. That limits the impact of application changes to the high level test scripts which use the APIs I create. Thus, if a change occurs in the application which can break the tests, then I change one file versus many.

The above may be a topic of another post one day. I will now get on with showing the tooling.

First, and not really shown here, I needed a way to proxy calls to a Selenium session. I created a library which implements certain aspects of Selenium to allow this to happen. This simply gets and sets the Selenium session ID so calls for a Selenium session may come from multiple places. In this case, the user serializes those things. You will see it references in code which follows.

Next, I needed a way to manage Selenium server connections, and too I needed a simple way to kick off a Selenium server in the development environment. The "Selenium Manager" top component handles this for me. Certain aspects are configurable.





You can also start and stop the in IDE Selenium server here. The output uses the NetBeans output window for this.



Once you have configured connections, you can start and use them one at a time


Once a live session is available, the manager allows you to stop it or to copy the session ID using context menus


Next, and most importantly, there is the ability to do productive things.

There is a Selenium JavaScript runner. This is a special window where one can type in JavaScript, execute it, and see the response. Too, one can ask for the current HTML from the page based on the DOM and not the plain HTML sources before any JavaScript logic has applied changes.


Notice the syntax highlighting options in the output below. I suppose I could add the ability to view that as JSON too. This is an example of using the "Grab HTML" button



Notice the part above dealing with ret=ret in the JavaScript image. This is due to the way this logic will be run directly in Selenium and the way it returns the last evaluation instead of having the caller use the return statement; this is a Selenium thing (see Selenium.getEval). That could have been worked around in the JavaScript runner if I had put the logic in a function and called it, but for the purposes of using this window that is a little overhead I don't need.

Above, you may have noticed the use of jQuery. How did it get there? Right, there is a difference in the JavaScript used in your application, and that used in Selenium. You can see my other blog post for more information, but I injected jQuery into the current Selenium session using Selenium.addScript from some Java code.

I will show you how that gets there in a bit.

It should be obvious we are using the started session here, but just to be clear, before I can run this JavaScript, I had to start a Selenium session and drive the state of the browser manually to get to what I wanted to operate against. In this case not really as the session opened on the Google home page.

Above, I mentioned injecting jQuery. Well, if you can inject jQuery, then you can inject your own JavaScript as well. You can take the logic you figure out in the JavaScript runner and move that into your own JavaScript files which you will inject.



Next, you can create a regular Java project in the NetBeans IDE. Then, you can create a standard Java class. You can then click on a line in the Java file and bring up a context menu and ask the tooling to inject the required Selenium proxy logic to allow you to write code using the current session.


This can be in a main method as above in which case it will be a local variable, or it can be at the class level. Repeated uses of the above action will just overwrite the previously injected code unless it is deleted; in that case it will be added back. This is needed if you stop the Selenium session and restart it. In this case you get a new session ID. Once you use the action, your class will look like this


Then you fill in some scratch pad type code to exercise some logic you will later add to an actual API. This may seem counter intuitive, but the point is to be able to drive the state of the application with the browser while you write some finite pieces of the whole which you know work. This greatly reduces the time to get the state in place and start the test etc. The develop test cycle becomes easier to manage.



So, how did our JavaScript and jQuery come to reside in the Selenium session? It was put there with another scratch pad Java class.


The related libraries were added to my Java project automatically for me by the tooling too. This includes the proxy library which I first wrote about.


I'm obviously trying to use a very simple example here. To get real work from these tools I have a full blown AUT API I have designed and developed for the project I'm testing. Too, I have developed the infrastructure needed to use the API including a set of tests and Ant build scripts.

The individual tests I can run directly from the IDE as they are JUnit tests, and their core logic can be developed, along with the APIs, running against a live Selenium session. The Selenium JavaScript injection is done automatically by my base JUnit test along with other preliminary things.

Hopefully at some point in the near future I will create an OSS version of this tooling. I don't have an ETA at this moment. But, I hope as I feel it could be useful for many.

2011-04-11

Using Selenium and jQuery for Automated User Testing

I am assuming you are familiar with both jQuery and Selenium. Too, I'll assume you want to use jQuery inside locators or in some way through Selenium to make locators easier using more utilities. So, I'll show you how to do that as well as use your own custom JS files and logic through Selenium just the same by using Selenium.getEval.

First, the below is made possible using the Selenium command or API call addScript. Next, we need a way to take our file or URL based resource and convert it easily into a string which is what addScript is expecting. I use this utility I have:

 public static String inputStream2UTF8(InputStream in) throws IOException {
String ret = null;
BufferedInputStream bin = new BufferedInputStream(in);
InputStreamReader isr = new InputStreamReader(bin, "UTF-8");
StringBuilder sb = new StringBuilder();
int iread = -1;
while ((iread = isr.read()) != -1) {
sb.append((char) iread);
}
ret = sb.toString();
return ret;
}


Next, I like having a more utilitarian method of injecting these resources into the current Selenium session. I use the following two methods together:


/**
* Merges all these different resources into a single input stream, puts them
* into a single JS memory file, and injects this into Selenium using the given
* js element tag ID (jsTagID).
* @param resourceLocator class used to locate resources using cpResourcePaths
* @param cpResourcePaths resource paths relative to resourceLocator or fully qualified
* @param filePaths file system paths, these can be relative if used from a
* running directory, but generally should be full
* @param jsTagID the ID of the script element to inject into Selenium
* @param se the Selenium instance to inject into
*/
public static void injectJavaScriptResourcesTogether(Class resourceLocator,
String[] cpResourcePaths,
String[] filePaths,
String jsTagID,
Selenium se) {
ArrayList ins = new ArrayList();
try {

for(String cpResourcePath : cpResourcePaths){
InputStream in = resourceLocator.getResourceAsStream(cpResourcePath);
if (in != null) {
ins.add(in);
}
}

for(String filePath : filePaths){
File f = new File(filePath).getAbsoluteFile().getCanonicalFile();
InputStream in = new FileInputStream(f);
ins.add(in);
}

SequenceInputStream sin = new SequenceInputStream(Collections.enumeration(ins));

String js = inputStream2UTF8(sin);

//don't swallow here...let the caller do that if
//they need to. API should not eat exceptions generally
se.addScript(js, jsTagID);

} catch (Throwable e) {
if (RuntimeException.class.isInstance(e)) {
throw RuntimeException.class.cast(e);
} else {
throw new RuntimeException(e);
}
} finally {
for (Closeable closer : ins) {
try {
closer.close();
} catch (Throwable e) {
}
}
}
}

public static void injectJavaScriptResource(Class resourceLocator,
String cpResourcePath,
String jsTagID,
Selenium se) {
ArrayList closeables = new ArrayList();
try {
InputStream in = resourceLocator.getResourceAsStream(cpResourcePath);
if (in != null) {
closeables.add(in);
}
String js = inputStream2UTF8(in);

//don't swallow here...let the caller do that if
//they need to. API should not eat exceptions generally
se.addScript(js, jsTagID);

} catch (Throwable e) {
if (RuntimeException.class.isInstance(e)) {
throw RuntimeException.class.cast(e);
} else {
throw new RuntimeException(e);
}
} finally {
for (Closeable closer : closeables) {
try {
closer.close();
} catch (Throwable e) {
}
}
}
}


You can see in the logic above that I attempt to locate the resources given to the methods in different ways. That is pretty straight forward, so I will let the code document itself.

Next, I add JS files into my Java project in NetBeans in a Java package. I will access those things as classpath resources per the code above. I use the following code below from some of my other source code:

public void injectSupportingJavaScript() {
ArrayList closeables = new ArrayList();
try {
String[] resources = new String[]{
"resources/jquery-1.4.4.min.js",
"resources/utils.js",
"resources/nav-utils.js",
"resources/image-dialog-utils.js",
"resources/asset-dialog-utils.js",
"resources/module-utils.js"
};

try {
SEUtilities.injectJavaScriptResourcesTogether(getClass(),
resources,
new String[0],
"ff-aut-javascript",
se);
} catch (Throwable e) {
log.log(Level.WARNING, "Unable to inject required Java Script as a single stream. Will attempt to inject the required .js files individually and continue to run.", e);
try {
for (int i = 0; i < resources.length; i++) {
SEUtilities.injectJavaScriptResource(getClass(), resources[i], "ff-aut-javascript-" + i, se);
}
} catch (Throwable e2) {
StringBuilder emsg = new StringBuilder();
emsg.append("Unable to inject required Java Script as individual streams. ");
emsg.append("Will not be able to continue as the locators can not be used in testing. ");
emsg.append("Selenium may need to be hacked a bit, or ");
emsg.append("the Firefly AUT API .js files need to be further broken up. ");
emsg.append("This is because Selenium HUB has issues with too large of requests. ");
emsg.append("The API already tries to compensate for this, and this measure has failed ");
emsg.append("which usually indicates a .js file injected into Selenium at test time has ");
emsg.append("grown too large in size.");
log.log(Level.SEVERE, emsg.toString(), e);
}
}

} catch (Throwable e) {
if (RuntimeException.class.isInstance(e)) {
throw RuntimeException.class.cast(e);
} else {
throw new RuntimeException(e);
}
} finally {
for (Closeable closer : closeables) {
try {
closer.close();
} catch (Throwable e) {
}
}
}
}

Notice the part about a single resource versus individual in the logic. I do this because there is an issue with Selenium Grid where it seems to use HTTP GET instead of POST in some cases where it should be using POST; at least this is my assumption per the error messages I received. This provides a decent fall back.

In the above, your custom logic will obviously need to inject your own .js files and those will need to be relative to your own class. Once you do that, you can then create a Selenium locater using either pure jQuery inline or you can use your own JS functions to limit the JS logic you have to place in Java files.

Too, using Selenium.getEval(String) you can execute JavaScript directly in the Selenium session. Sometimes you need to do this if your logic depends on some jQuery event listeners and the standard Selenium calls will not activate that logic correctly.

The one caveat to using these things, due to JavaScript targeting, is always pass in window.document to jQuery or your own custom JavaScript functions. The reason is that Selenium will be running in a separate browser window from your application. window.document will point to the window where your applications DOM resides. If you have any question about that specifically let me know.

Some locater example might be:
"dom=your_js_function_doSomething(window.document);"

For getEval it would simply be:
"your_js_function_doSomething(window.document);"

Remeber, the last evaluation or the return statement will be what Selenium returns to the calling logic. Too, you can use the throw statement in your JS to propagate better messages to the calling Java logic.

Enjoy.

2011-03-31

Multi-line HTML Tag Parsing with Regular Expressions and Java

I was looking at some regular expression related posts earlier today, and I noticed many of them showing something along the lines of:

<a\\b[^>]*href=\"[^>]*>(.*?)

The issue is in the
.*?

That may exclude line terminators. If you use
[\\W\\w\\s]*

in place of that. It will work around the line terminator issues. That is unless you are specifically looking for some specific tag without a line terminator.

2011-02-04

MochaHost: Was hoping they were going to be reliable Java hosting company; they are not even close

Recently I had the displeasure of trying out http://www.mochahost.com. I noticed their price points, and too they offer VPS for what seemed to be a great price. However, with hosting services, the ability to provision a new server in a timely manner, good customer service, infrastructure which just works, all matter. My experience was lacking in every way.

First, provisioning the VPS took over a week. I used their online live chat, and too I emailed their support. After days I finally had some information. They said their billing system had a bug in it, and they didn't receive my order until later. OK, I can give someone that initially; wasn't warm and fuzzy, but I could deal.

Next, I didn't know anything about their services, so I used a prepaid card to register, and only registered for a month. Thirty dollars US seems a great deal for a 1GB RAM bursting to 1.2-1.6GB VPS. But, I like to try things out in the safest way possible as you never know who is fronting a criminal or poorly managed or insecure business. No lock in and a safer card.

I recommend small businesses adopting the prepaid card trick by the way, and too, never EVER sign up for something over a month on contract until you have tried it out. VERIFY!

Well, they double billed me as soon as they got the server set up. The card declined. They turned off my service. This after they had a history of me writing their support and asking where the system I had already paid for was. Back to support I go.

I write support, and I explain the situation, and I go ahead and copy and forward previous emails. They wrote back apologizing, and said they changed my invoice date etc. OK, server on, lets try it out.

Well, they use WHM and cpanel. During the stint with the card, their automated processes have disabled those. Now, I can't manage things through those interfaces, and too, I'm paying a little extra for those programs; they force you to pay that extra amount on account creation; must have some panel with their VPS.

I'm sitting wondering after all which has occurred why they didn't verify the system. Not looking good. So, I write them again. At this point most would have walked away I'm sure. But, I was wanting a beating.

They tell me they have it fixed. I get into WHM, and there isn't much I can manage there. Too, cpanel isn't setup; I can't log into the system through it. I get some weird error.

I mean, I am using a hosting service right? Kind of the point: I don't have to manage "everything".

I write them and explain that I don't want WHM nor cpanel which they forced me to pay extra for and use at sign up. I tell them it seems it is just not working with their VPS configurations, and it doesn't; even email account configuration seems to not exist. I tell them I don't want to have it on the system at all, and that way I can try out their rest of their services and support without it, and that I use Linux all the time and would just rather the command line. I even tell them I could write about this experience one way or another, and the ball is in their court, but that I'm still willing to see what they have.

I say a) I want the system freshly installed b) no WHM or cpanel or to at least know if that is a possibility c) explanation of whether the "unlimited" email accounts are to be on the VPS or through other hosted services they may have, and roughly that is about all I want less their promised 99.9% up time outside of my own coding or GlassFish 3 crashes if they occur.

I get an email back asking me to detail what I expect. So, I go into the details again. Too, I ask them to review the history of my account, and why I am dissatisfied with their service. I even tell them they should be reviewing this case to help make their business better, because there is obviously something wrong. The whole time, outside of explaining this is something I've paid for, I'm deliberately polite.

I get another email back telling me they can't do anything with my account until I take care of an outstanding balance! This being the double bill. I sent them a copy of my receipt, the transaction ID from the CC company, and asked for my money back.

We'll see if that happens or not, but just be warned. MochaHost is not what you're looking for if you want anything remotely close to good service. At this point, service under par would be good. END RANT

2011-01-28

Java, @Override, and refactoring

We have been making some changes to the user interface of a project of which I'm a member. This requires me to change some automated user testing APIs and interfaces to match the new reality.

I don’t remember exactly who I was talking one day when they mentioned my use of the @Override annotation even when implementing interfaces. I told them the IDE added that, and I just left it at that. I couldn’t think of a great use case for that being there at the time, but since the IDE did it for me I figured there must be some point even in the case of interface implementation, so I left it in the code as it didn’t cause any issue and was correct logic.

Now that I have begun to refactor and remove some methods which no longer make sense, I am finding the @Override annotations very useful because the IDE points out what is implemented as an @Override when it isn’t actually overriding anything from a super class or interface. This is a compile time error, and were I not using a fancier IDE, I would still be alerted to the problem when the project was compiled. Thus, the annotation has been a nice aid in this type of refactoring.

This would also be the case of an actual method override in the case where the super method was not called from the override. In such a case, and without @Override, the logic would simply no longer be used, but would compile just fine. The call would be removed from calling code of the super class or interface for the obvious compiler reasons one would encounter, but if someone left that logic in the existing class by mistake, and someone thought it should be called because some other state depended on it without that class being rethought at the time of some major refactoring, then a serious issue has been introduced which could be hard to figure out.

I wanted to share this with everyone as I believe it can help everyone if @Override is always used. If you have a different opinion or thoughts on the topic please share.