When performance testing demonstrates a bottleneck in an integration that is seamless to the end user, how do you pinpoint where the problem lies? On a recent project, I was asked to test the addition of a survey hosted at a third-party site. Once the user completed the survey and was redirected back to the page from which they were diverted, there were several seconds of delay.
As recorded, this “complete survey > process survey > return to original site” step was only one function:
web_submit_data(“CompleteSurvey.aspx”,
“Action=https://my.thirdpartysite.com/Survey/SurveyLastStep.aspx?id=34bsd3902842s-34d3”,
“Method=POST”,
“TargetFrame=”,
“RecContentType=text/html”,
“Referer=https://my.thirdpartysite.com/Survey/SurveyPreviousStep.aspx?id=8977sd324802-43ds”,
“Snapshot=t73.inf”,
“Mode=HTML”,
LAST);
To the end user, the process seemed to be simple. They clicked “Finish,” and returned to the page they were on before they began the survey. However, looking at the recording snapshot reveals a more complicated route involving a series of redirects:
The first redirect was still on the third-party site. This step processed the survey answers. The second redirect was to the original site, returning the user to the page they were on before they took the survey. A replay of this process revealed the entire trip took in excess of eight seconds.
Because a performance problem was identified, it was important to pull out the redirects into their own function calls and wrap transaction timers around them. Did the problem lie on the third-party site or elsewhere? To find out, the solution below was implemented:
// Essentially, turn off redirects
web_set_option("MaxRedirectionDepth", "0", LAST);
//Register a save parameter for the redirect location header
web_reg_save_param_ex(
"ParamName=cRedirectProcessSurvey",
"LB=Location: ",
"RB/RE=\\\r\\\n",
SEARCH_FILTERS,
"Scope=HEADERS",
LAST);
//Begin original transaction timer
lr_start_transaction("AUT_T016_SubmitSurveyAnswers");
//Begin a sub-transaction timer
lr_start_sub_transaction("AUT_T016_SubmitSurveyAnswers_001_SubmitAnswers","AUT_T016_SubmitSurveyAnswers");
//Submit survey answers
web_submit_data("SubmitSurvey.aspx",
"Action=https://thirdpartysite.com/Survey/SubmitSurvey.aspx?sid={cSurveyID}",
"Method=POST",
"TargetFrame=",
"RecContentType=text/html",
"Referer= https://thirdpartysite.com/Survey/Page5.aspx?sid={cSurveyID}",
"Snapshot=t73.inf",
"Mode=HTML",
ITEMDATA,
"Name=__LASTFOCUS", "Value=", ENDITEM,
"Name=__EVENTTARGET", "Value=", ENDITEM,
"Name=__EVENTARGUMENT", "Value=", ENDITEM,
"Name=__VIEWSTATE", "Value=", ENDITEM,
"Name=ctl00$ContentHolder$hidFinish", "Value=1", ENDITEM,
"Name=ctl00$ContentHolder$hidFinishButton", "Value=Next", ENDITEM,
LAST);
//End the sub-transaction
lr_end_sub_transaction("AUT_T016_SubmitSurveyAnswers_001_SubmitAnswers ",
LR_AUTO);
//Register a save for the redirect to the originating site, our application under test
web_reg_save_param_ex(
"ParamName=cRedirectToAUT",
"LB=Location: ",
"RB/RE=\\\r\\\n",
SEARCH_FILTERS,
"Scope=HEADERS",
LAST);
//Begin a sub-transaction timer
lr_start_sub_transaction("AUT_T016_SubmitSurveyAnswers_002_ProcessAnswers","AUT_T016_SubmitSurveyAnswers");
//In this case, the location header contained a relative path. Absolute path prefix was added
web_url("ProcessSurvey",
"URL=https://thirdpartysite.com/{cRedirectProcessSurvey} ",
"TargetFrame=",
"RecContentType=text/html",
"Referer= https://thirdpartysite.com/Survey/SubmitSurvey.aspx?sid={cSurveyID}",
"Snapshot=t301.inf",
"Mode=HTML",
LAST);
//End the sub-transaction timer
lr_end_sub_transaction("AUT_T016_SubmitSurveyAnswers_002_ProcessAnswers",LR_AUTO);
//Return Max Redirection Depth to its original value
web_set_option("MaxRedirectionDepth", "10", LAST);
//Begin the last sub-transaction timer
lr_start_sub_transaction("AUT_T016_SubmitSurveyAnswers_003_RedirectToAUT","AUT_T016_SubmitSurveyAnswers");
//The location header contained the absolute path back to the original site
web_url("RedirectSmart",
"URL={cRedirectSmart}",
"TargetFrame=",
"RecContentType=text/html",
"Referer= https://thirdpartysite.com/Survey/ProcessSurvey.aspx?sid={cSurveyID}",
"Snapshot=t302.inf",
"Mode=HTML",
LAST);
//End last sub-transactions. You have all redirects timed now.
lr_end_sub_transaction("AUT_T016_SubmitSurveyAnswers_003_RedirectToAUT",LR_AUTO);
//End the original transaction timer.
lr_end_transaction("AUT_T016_SubmitSurveyAnswers", LR_AUTO);
When the changes were made to the script, a test was executed which found a bottleneck in the handshake that occurs between the third-party site and the application under test (the third step in the process or second redirect). Armed with this new information, I was able to help developers pinpoint the problem.
In most cases, it is not necessary to pull out redirects from the page which calls them. We are timing the experience of the end user as he or she moves through the application under test, and if a page redirects to another in a single end-user step, that entire process is the end-user experience and should be timed as such. Although in this case, developers needed to know the source of the bottleneck in the final step of the survey process. By temporarily turning off redirects, moving redirect URLs to their own web_url() calls, and creating sub-transaction timers, we solved the performance mystery.