JMeter

Jmeter with Spring Webflow

Theworkaholic Blog - Wed, 08/04/2010 - 06:44
Motivation
The application uses URL containing dynamic parameters and so a record/replay fails
http://www.mail-archive.com/jmeter-user@jakarta.apache.org/msg30317.html

Solution
This short tutorial deals with test scripts that interact with dynamic data, and we will choose a Spring Webflow example to write a test script against.
So we look around on Google for a sample Spring Webflow application which leads us to
Spring By Example Sample
I'm not going to use the JMeter Proxy Recorder because it seems to harm beginners more than it helps. Testers seem to get the impression that all they need to do is record and replay the script and they are done. So I shall use Firefox and LiveHttpHeaders. We are going to Login to the site and create a User

Step 1: Request the Login Page

http://www.springbyexample.org/simple-webflow/login.jsp
GET /simple-webflow/login.jsp HTTP/1.1

Response
HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=[uniquevalue1]; Path=/simple-webflow

So the first request response shows that the system sets a cookie and the name should tell us that this is a session id. [TODO]. This should also indicate to us that we need to add a cookie manager. Note the status is 200 in the Response. This is the server telling us all is well.

Step 2: Submit Login

http://www.springbyexample.org/simple-webflow/loginProcess;jsessionid=[uniquevalue1]

POST /simple-webflow/loginProcess;jsessionid=[uniquevalue1]
HTTP/1.1
Cookie: JSESSIONID=[uniquevalue1]
Content-Type: application/x-www-form-urlencoded
Content-Length: 48
j_username=david&j_password=newyork&submit=Login

Response
HTTP/1.1 302 Moved Temporarily
Date: Tue, 17 Aug 2010 05:03:48 GMT
Set-Cookie: JSESSIONID=[uniquevalue2]; Path=/simple-webflow
Location: http://www.springbyexample.org/simple-webflow/index.jsp
----------------------------------------------------------
http://www.springbyexample.org/simple-webflow/index.jsp
GET /simple-webflow/index.jsp HTTP/1.1
Cookie: JSESSIONID=[uniquevalue2]

HTTP/1.1 302 Moved Temporarily
Location: http://www.springbyexample.org/simple-webflow/index.html
----------------------------------------------------------
http://www.springbyexample.org/simple-webflow/index.html
GET /simple-webflow/index.html HTTP/1.1
Cookie: JSESSIONID=[uniquevalue2]
HTTP/1.1 200 OK

a. The browser sends back the cookie that was previously set. However note that the URL also has a jsessionid which has the same value as the cookie that was set. This is known as URL rewriting. Our test will ignore this value because we will be using a Cookie manager
b. The server sends a 302 response to the request. This basically asks the browser to request a new URL (the one that the Location Response Header has). Note this can happen more than once as the next request too results in a 302 response, which finally results in a 200 status code.
HTTP Status Codes are discussed here
c. The server also sends a Set-Cookie for JSessionID again with a new value. This is usually done for security reasons. We can ignore this for JMeter because the Cookie manager will handle this for us. However the sampler that we use needs to have follow redirects set. If redirect automatically is set , JMeter would not get to see this Set-Cookie header and since the application has switched the session id , if you sent it the old session id (which was associated to the before login session)

Click the Create Link

http://www.springbyexample.org/simple-webflow/person.html
GET /simple-webflow/person.html HTTP/1.1
Cookie: JSESSIONID=[uniquevalue2]

Response
HTTP/1.1 302 Moved Temporarily
Location: http://www.springbyexample.org/simple-webflow/person.html?execution=e1s1

----------------------------------------------------------
http://www.springbyexample.org/simple-webflow/person.html?execution=e1s1
GET /simple-webflow/person.html?execution=e2s1 HTTP/1.1
Cookie: JSESSIONID=[uniquevalue2]

HTTP/1.1 200 OK
Date: Tue, 17 Aug 2010 05:06:04 GMT

Clicking the Create link also resulted in a 302 code so the browser issued a new request. But take a look at the URL. It has a parameter named execution with a value e1s1. Now click the link again.

Click Create link again

http://www.springbyexample.org/simple-webflow/person.html
GET /simple-webflow/person.html HTTP/1.1
Cookie: JSESSIONID=[uniquevalue2]

Response
HTTP/1.1 302 Moved Temporarily
Location: http://www.springbyexample.org/simple-webflow/person.html?execution=e2s1
----------------------------------------------------------
http://www.springbyexample.org/simple-webflow/person.html?execution=e2s1

GET /simple-webflow/person.html?execution=e2s1 HTTP/1.1
Cookie: JSESSIONID=[uniquevalue2]

HTTP/1.1 200 OK

The "execution" parameter value changes! So if you run the same test multiple times , the value has to be different. This is a common cause of failure of Record / Replay tests. Some of the data is dynamic. This data can be of various forms
a. Something the application framework needs
b. Something where the data varies (E.g. the UserId, the Product ID). Typically a user friendly string is shown on the screen but when the user performs an action , an id (usually a key in the database) is what is used by the application
c. Dynamic fields (E.g. DHTML based applications) which get added on the fly.
To deal with this parameter/URL we need to be able to extract the value from previous requests in our JMeter scripts.
If you haven't developed the application it may be difficult to identify whats dynamic and whats not. The easy way is to record the script twice(With different data) and observe what changes. e.g. if you browse a product catalog , change the product.

Submit the form

http://www.springbyexample.org/simple-webflow/person.html?execution=e2s1

POST /simple-webflow/person.html?execution=e2s1
HTTP/1.1
Cookie: JSESSIONID=[uniquevalue2]
Content-Length: 56
id=&firstName=deepak&lastName=shetty&_eventId_save=Save

Response
HTTP/1.1 302 Moved Temporarily
Location: http://www.springbyexample.org/simple-webflow/person/search.html
----------------------------------------------------------
http://www.springbyexample.org/simple-webflow/person/search.html
GET /simple-webflow/person/search.html HTTP/1.1
Cookie: JSESSIONID=[uniquevalue2]

HTTP/1.1 200 OK

Unfortunately the application has a visual bug, the added user does not show. However if you do a view source on the page and search for the username you created you can find it.

Click Logout

http://www.springbyexample.org/simple-webflow/logout
GET /simple-webflow/logout HTTP/1.1
Cookie: JSESSIONID=[uniquevalue2]

Response
HTTP/1.1 302 Moved Temporarily
Set-Cookie: SPRING_SECURITY_REMEMBER_ME_COOKIE=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/simple-webflow
Location: http://www.springbyexample.org/simple-webflow/logoutSuccess.jsp
----------------------------------------------------------
http://www.springbyexample.org/simple-webflow/logoutSuccess.jsp
GET /simple-webflow/logoutSuccess.jsp HTTP/1.1
Cookie: JSESSIONID=[uniquevalue2]

HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=[uniquevalue3]; Path=/simple-webflow


The JMeter Script
Now that we know the above we can get to writing the script

Most of the script is pretty much standard(All Samplers use follow redirects and we have added a Cookie Manager), till we get to the point where we need to extract out the URL.
The Request Create Sampler extracts out the URL. Since we know that the application is going to redirect us , the extracter will extract out the last URL we will be on



The Post Create Data Sampler simply uses this extracted URL



Note that all samplers have assertions that verify the behavior, so if something goes wrong the Assertion should fail. For e.g. after creating the user we verify that the user we created exists on the page. When requesting a page the assertions verify some text on the page that is unique to the page.
Run the test, we get no errors! Modify the ThreadGroup to have two threads and two iterations. Run the test , everything should pass. Now look at the View Results Tree listener. You should see the redirects being followed (multiple children results under a parent). But do you see different values for the execution parameter? No - This is because each thread is its own session and each user will start with the same parameter value. Even having multiple iterations on the thread group doesnt give you different values because we are logging out at the end of the script so the next iteration is a new session.

Try adding a Loop controller to create 10 users. Note that the loop controller must enclose the Request Create and Post Create samplers (because we need to extract a new value for the execution parameter every time!). Using View results tree you can now observe the execution parameter changing.



Sample Script
Spring Webflow.jmx

Spring Webflow with loop.jmx
Categories: JMeter

Lessons from kid entrepreneurs

10 Jumps Blog - Mon, 06/28/2010 - 17:31

Most parents are  painfully aware that summer vacations are in full swing. Just filling your kids’ day with meaningful activities becomes challenging. Some choices are free play in the backyard / local neighborhood, watch TV or attend expensive summer camps. Well in reality it is a little of all of these.

However, with my nieces visiting me this summer, things have become a little more challenging. There are three girls (including my daughter) aged 7-10 whom I will have to entertain endlessly to fulfill my avuncular duties. OR so I thought. This weekend we decided to put up a lemonade stand in our local city parks. And boy, did I just open a can of fun and hyper excitement for them. My only instruction was – “make it happen.”  Given how much I learnt from the entire exercise, I was the main winner.

Planning:

The girls got up early and like any meticulous project manager charted out all the required ingredients ( including music and decoration for the stall). The list was quite thorough including items like tape for putting up the decoration. The tasks were also well defined with clear responsibilities. There was a chief decorator (to make posters), chef (to prepare lemonade), and item collector to make sure all items for the stand are procured. The name of the venture – ARA (for the initials of the kids)

Lesson: Planning is crucial even for seemingly small tasks.

Preparation:

With everybody’s duties charted out, all the 6 hands were on board. Making posters with bright colors, preparing lemonade per very accurate measurements, and making sure there were enough glasses, napkins, garbage bags, etc. Everyone was cross checking with others to make sure all was fine and on track.

Lesson: Lean, just in time, Kaizen execution at its best. Parallel processing, with highest priority to problems in the assembly process.

Start of business:

By late afternoon we were all ready to hit the biggest park (to get most customers). with all items carefully stacked up in the car, icebox filled with fresh ice, we set off and sat up our modest stand. Of course the kids had a picture in mind that the moment the stand is set up, people will flock over and buy all the freshly squeezed, zesty, sweet-tarty lemonade. But things were turning out a little different. No one cared about our stand and there were no sales. 5 minutes into it, they were looking completely beaten down due to zero sales. The three were looking at me waiting for some magic to happen. I didn’t know what to say. If you have dealt with kids that age, patience was not a good word for the moment. All I could say was go do some direct sales and advertise your stand to people. Off the three darted and told every parent and the kid nearby about the stand. Still no orders. No volume sales. This only made the kids more determined and now they added the option to deliver the cold refreshing glass to where ever parents were sitting / standing.

First customer

The first customer was a nice gentleman who really appreciated the efforts the children were making. He agreed (actually offered) to have a picture taken. This was the start of the venture.

all set up

The orders started rolling in, 1 glass, 3 glasses and eventually we sold 14 glasses in 30 minutes. Things slowed down quite a bit after that. We decided to move to a smaller park which would be denser and more packed with people. Everyone who had the lemonade really liked it, but there were few new customers coming in now.

Lesson:

1. Impatience is also a virtue. I would have waited longer to push the sales.

2. Sales needs courage. The kids were really bold to walk up to strangers and sell the idea of a refreshment. I would have been more hesitant.

Business takes off!!

We drove to a different park with fewer people, but the people were more densely packed. Instead of advertising to parents, team ARA started advertising to other children. These were the primary users and and our allies. These kids (ultimately our uses) did the work to persuade their parents and now the orders really started coming in. As the crowd gathered, we attracted more attention and more people came over.

Now emboldened, team ARA tried something new – approaching the people playing basketball, volleyball or other physical sports. Now this was the kicker. We were really serving a pain point. These were the thirstiest people on the play ground. They had the money and would also recommend the product to others reducing our sales or advertising efforts. This is exactly what happened. Now we were not able to keep up with the demand. In 20 minutes we were sold out. All 3 gallons, just wooshh. The kids were having so much fun, yelling with every new order, and thanking all customers with their heart. Everyone around now knew what we doing in the park.

Lessons: Several

1. Product placement is very important. First location was not conducive to volume sales, but the second park was.

2. Serve the pain point

3. Don’t just reach to the decision makers but also the users and persuaders

4. ENTHUSIASM for your product is very very important

5. Have a good product.

At the end all the lemonade was sold. Kids had PLENTY of fun. They learnt a few lessons in costing, pricing, product placement, sales, marketing and users. For me, it was just refreshing to see some of the complex business phenomenon unraveling in a simple scenario like a lemonade stand.

Most importantly, I discovered an alternate way to engage the kids and have plenty of fun.

Categories: Cloud Computing, JMeter

Changing face of search with RDF and Facebook – impact on Drupal

10 Jumps Blog - Fri, 06/25/2010 - 23:24

RDFa (or Resource Description Framework – in – attributes) is a W3C recommendation that adds a set of attribute level extensions to XHTML for embedding rich metadata within Web documents.

This metadata protocol (RDFa) is used by the open graph protocol to enable any web page to become a rich object in a social graph. Facebook uses the open graph protocol to to make any web page look like facebook’s pages.

Example of properties defined in the open graph protocol are (Refer http://opengraphprotocol.org/ for more details):

  • og:title – The title of your object as it should appear within the graph, e.g., “The Rock”.
  • og:type – The type of your object, e.g., “movie”. Depending on the type you specify, other properties may also be required.
  • og:image – An image URL which should represent your object within the graph.
  • og:url – The canonical URL of your object that will be used as its permanent ID in the graph, e.g., “http://www.imdb.com/title/tt0117500/”.

Great – so what about it?

Recently Dries Buytaert gave his keynote at DrupalCon (which I highly recommend watching) and laid out the support for open graph protocol in Drupal 7. Meaning that Drupal 7 will inherently support RDF. Here is an update on the progress of this feature in Drupal 7.

Facebook CEO Mark Zuckerberg also announced his support for open graph protocol in Facebook. 10s of thousands of website have converted their sites to also publish data in open graph protocol using RDF.

Essentially all this makes sense if you also read the post which talks about Facebook search strategy. Facebook will compete with Google in the search market. The sites that implement the open graph protocol to publish data have inherent advantage of being indexed, searched and presented along with Facebook search results. This is huge for websites, since users can ‘like’ a site or ‘comment’ on a site like they do to native Facebook objects. The websites would get a lot direct feedback. This would also make the search results more relevant over time since there is a significant user input.

This will give facebook a Semantic search engine enriched by inputs from its 100s of millions of users. And to Drupal websites an easy hook to leverage this move seamlessly to their advantage.

Categories: Cloud Computing, JMeter

Split a large content type into separate tabs (Drupal)

10 Jumps Blog - Mon, 05/24/2010 - 02:12

As some you might have experienced, some of the content types in your Drupal site might get too unwieldy because of their sheer size. Displaying a form for the content type of displaying the node is not elegant anymore and the user has to scroll till figures hurt.

I had a similar situation recently (attached image with the fields lists all the fields in this ‘Event’ content type:

The simple and elegant solution is to divide the object into logical tabs both for the form and view. and the final output looked like below for me:

The way to achieve this is to:

1. Divide the fields in the object into fieldgroups, which will eventually be the different tabs (these are standard groups).

2. Have a custom module where you will override the form and do at least these changes:

2.1 edit form_alter hook to have something like

$group_eventcontacts = $form['group_eventcontacts']; unset($form['group_eventcontacts']); $form['group_tabs']['group_eventcontacts'] = $group_eventcontacts;

where eventcontacts is the name of the fieldgroup. So we are creating a new group and removing the fieldgroup from the original form.

2.2. Override the theme hook to have the following:

return array( ‘myfunc’ => array( ‘arguments’ => array(‘form’ => NULL), ),

2.3 In the myfunc function:

have the following (refer 2.1 above):

$event_keyContacts = drupal_render($form['group_tabs']['group_eventcontacts']);

and append the $event_keyContacts variable to the $output.

$output .= <div id=”event_keycontacts-’.$nid.’”>’.$event_keyContacts.’</div>

Thats pretty much all for the form.

Do this for all the groups(tabs) you want to create .

3. Now for the node viewing part. I created a separate node-event.tpl.php for handling my event content type. This file is created in the theme directory.

$content = preg_replace(‘~<fieldset.+ class=”content-multigroup-group-eventcontacts”?</fieldset>~s’,”,$content);

this removes the fieldgroup content from the $content. Do this for all the groups.

Now get the contents from $node->content

if (isset($node->content['group_eventcontacts'])){ $group_eventcontacts = $node->content['group_eventcontacts']['#children'];

Add the $group_eventcontact variable to the tab

$tabs_div .= ‘<div id=”event_contacts-’.$nid.’”>’.$group_eventcontacts.’</div>’;

It is important to understand the difference between $content and $node->content. Former is the formatted representation of the content and later is a data structure containing the contents. $node->content has to be themed to become $content. There be sure to manipulate both variables correctly.

That is all for getting the tabs.

Happy coding

Categories: Cloud Computing, JMeter

Selling onDemand paradox and your target audience

10 Jumps Blog - Sat, 05/08/2010 - 21:57

Is it the dizziness from dealing with IT for so long or a new found love for a 3 letter acronym – LOB (Line of Business). Why does every one talk about onDeman and LOB in one breath and one sentence. There are different models of offering an on demand solution. Each of the them could be (should be and is) for a different target audience.

While it is correct to assume that SaaS (or applications on demand) is targeted towards LOB, the same cannot be assumed for PaaS and IaaS.

Platforms are for developers and Infrastructure is for IT / developers. The fact that IaaS solutions should have a buy in from IT departments is where I find a break in the value chain. If public clouds which offer IaaS optimizes data centers then there will be an inflection point where IT departments will have low tolerance for these solutions. Not because they don’t want improvement, but because these solutions will undermine the effectiveness of the IT department.

So essentially, these companies are selling to a set of users who will be displaced by buying these solutions. This logic alone makes IaaS a risky model especially if most investors and supporters think only of Line of Business. LOB will not buy Infrastructure services.  Isn’t that the whole point of selling to LOB – they want on demand running solutions with low barriers to buy and deploy (and possibly bypass corporate IT).

So for all the proponents, investors and evangelists of onDemand it is important to understand the different target customers for the different onDemand offerings and not put a blanket LOB assumption. How to sell IaaS to IT is a completely different animal and someday I hope to blog on the subject as well. For now I know that corporate IT is likely to use all the ammunition to deter public cloud adoption in their companies, unless they are forward thinking and understand that they get to move up the value chain as well.

Categories: Cloud Computing, JMeter

emails could be marked spam if the email server is in EC2

10 Jumps Blog - Thu, 05/06/2010 - 18:33

Its a known fact that all the cloud offerings are different from each other. Weather they are big or small players, everyone is innovating at break neck speed and there is no point in comparing feature by feature because such a comparison could be obsolete before it is useful.

I have a personal bias towards Amazon’s EC2 because I have spent most time on it, and it seems to be far ahead of rest of the herd. However, I don’t find everything easier and nicer in Amazon. Some use cases can be very simple and EC2 would be an overkill or insufficient. One example is if I want to host a website in the cloud.

Sure, I could go with a traditional web hosting company, but if my requirements needed me to look at IaaS providers then there are a couple of things to consider. I found setting email servers in Amazon extremely challenging. Part of the reason could be the way they have reverse DNS set up.

First a few basic concepts.

1. DNS / reverse DNS: Without getting into too much details, DNS is what let you have names for a website (www.mycompany.com). Without it, we would have to refer to websites with IP addresses (e.g. 192.1.4.80). By looking up DNS servers the URLs (domain names) are converted to an IP address and the site is found and loaded. This is all transparent to the end user.

Similarly reverse DNS (rDNS) allows programs to find names, given an IP address. One of the uses of rDNS is for spam email prevention by SMTP servers (emails servers). The mail servers check if the email actually originated from the DNS name that it says it came from.

2. How DNS is configured in Amazon instances: Each Amazon instance has an internal and an external DNS name. Usually you would map your wesites name (www.mycompany.com) to the external DNS of the instance. This would get translated to the internal DNS name of the EC2 instance. CNAME is used to make the mapping between your domain name and Amazon instance. (Also the suggested way by Amazon)

However, if an email server is hosted on the Amazon instance and you send an email from the server, the reverse DNS resolves to the external DNS provided by Amazon, and not to your mapped domain name (www.mycompany.com). Therefore the email receiving server will not be able to correctly resolve the DNS name raising the probability that your emails from Amazon server are marked as spam.

There are other options to host web servers and email servers where service providers have optimized the setup for exactly this purpose. I have only looked at a few and Slicehost (now owned by Rackspace) seems to have a very good offering and a network setup. I just wish it were a little cheaper.

Categories: Cloud Computing, JMeter
Syndicate content