I'd like to setup a JMeter test plan to suggest whether a web site (URL) is Drupal-based (based completely on the HTTP response from the site) and compare it with existing data that I have on the environment. (I realize that using an HTTP approach, as opposed to say examining the site's file system, is "iffy" but I'm curious how useful the approach is)
The JMeter command line might look like this:
JMeter -t "DrupalAssertions.jmx" -Jurl=http://my.dot.com -Jdrupal=true
where I provide the URL to test and an additional property "drupal" indicating my best guess on whether the site is Drupal-based.
In my test plan, I add an HTTP Request to return the HTML content of the page for the URL. I'm then able to successfully add a Response Assertion that tests a pattern (say (?i)(drupal) for a sadly lacking pattern) to see if it's contained in the response.
That much works fine, or as expected, but what I'd like to do is to compare the value of the "drupal" property against the result of that pattern test in that same Response Assertion. I know I'm missing something simple here, but I'm not seeing how to do that.
I want to try to use an expression like this:
(?i)(drupal) == ${__P(drupal)}
in a pattern, but that doesn't work. The name of the Compare Assertion looks promising, but I don't see how to incorporate the property into a comparison.
Update: The approach suggested by PMD UBIK-INGENIERIE does work. I used a Regular Expression Extractor like this:
<RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract Drupal in Response" enabled="true">
<stringProp name="RegexExtractor.useHeaders">false</stringProp>
<stringProp name="RegexExtractor.refname">drupalInResponse</stringProp>
<stringProp name="RegexExtractor.regex">(.*drupal.*)</stringProp>
<stringProp name="RegexExtractor.template">$0$</stringProp>
<stringProp name="RegexExtractor.default">__false__</stringProp>
<stringProp name="RegexExtractor.match_number">1</stringProp>
</RegexExtractor>
followed by this BeanShell Assertion:
// Variable "drupalInResponse" is "__false__" by default
if ( !(vars.get("drupalInResponse").equals("__false__") ) ) {
vars.put("drupalInResponse","true");
}
else {
vars.put("drupalInResponse","false");
}
print("\n\nThe value of property 'drupal' is: " + props.get("drupal") + "\n");
print("\n\nThe value of variable 'drupalInResponse' is: " + vars.get("drupalInResponse") + "\n");
if (vars.get("drupalInResponse").equals( props.get("drupal") ) ) {
print("Site Drupalness is consistent with your beliefs");
}
else {
print("You're wrong about the site's Drupalness");
Failure = true;
FailureMessage = "Incorrect Drupal assumption";
}
In the Regular Expression Extractor, I'd set a default value that I felt wouldn't be matched by my pattern of interest, then did an ugly verbose Java comparison with the "drupal" property in the BeanShell Assertion.
Wish somehow that the assertion could be made in a single component rather than it having two parts, but you can't argue with "working" :)
You can use a regexp extractir with your first pattern
Then use a Beanshell assertion which will use your variable and compare it to drupal property.
Related
(Edit: The answer is to use check 'Encode?'option in the HTTP Request. Please see Vinoth's Edit 2 and comment below, thanks!)
This is interesting!
I'm trying to parse a HTTP response which has (let's give concrete example,
bigH:"2a3a6CEH+iJakQpQtPm8efv"
Using Regular Expression Extractor when I try
bigH:"(.+?)"
it extracts the string but replaces all the "+" in the string with space. That is, instead of
"2a3a6CEH+iJakQpQtPm8efv"
it gives me:
"2a3a6CEH iJakQpQtPm8efv"
Note the space between H and i.
How can I stop it from replacing the "+" with a space? I'd really appreciate if someone can give an explanation also.
Btw, I tried (.+?) and (.\++?) and even ([.|\+]+?) - didn't work :(
Thanks,
--Ishtiaque
Updating with screenshots below:
Adding screenshots:
POST Response data:
After parsing with regular expression extractor in JMeter:
Side by side in Notepad++:
'Raw' tab shows the '+'s:
'HTTP' tab does not:
As you get the response in JSON format, I would go with JSON Path Extractor.
It seems to be a much easier approach than using Regular expression.
Below JSON Path should take care of getting the encoded string from your JSON & You should be able to access using ${bigH}.
Check this for more details (scroll down for JSON Path extractor details).
EDIT:
I was wrong that You get the response in JSON format. Are you trying to access - bigH:"XXX" - from script tag? For this, We have to use Regular expression extractor only or Beanshell.
<script type='text/javascript' charset='utf-8'>
registerSubmit(document.forms[0].elements['SubmitTopButton']);
registerSubmit(document.forms[0].elements['SubmitBottomButton']);
(function($) {
$(".wb_tsauthall").wb_tsauthall({
auth : "Authorize All",
unauth : "Unauthorize All",
locMsgKeys : []
});
$(".wb_newedit").wb_newedit({
labels:['Job','Code','Work Premium','Flat Rate','Premium','Shift','Sched Times','LTA','Sched Times w Breaks','Delete Details','Employee Holiday','Work Detail','Schedule Detail'],values:[105,103,200,206,204,450,401,500,461,199,900,100,460],bigH:"PVxUbYIODBT31j8IZnPGxF/9O1iuKAkFzTO9WhXu8An8hAUa22tLiWrEHz8v9SIu/NXZH1a5IxO0xYeNwRIYM+3n1kNsrESnhiAYhwhCiqUY9mI4hvEPgAOx7B+MEB8iSIUyNGNZbeGx9nSogFYpNrzmCXirW7Nm9Tn7owPKHmc8dOf5SZ+eDzAOHIB8+5YzQ3bIdFoe60hOMkyd7FiUXtwPcNMUFEjOSMs9JhgIHTE4agpCdbFb6SLuSuLoO9rqxj+9GovUbzTmrxj4faBKZVATNN7iIFyDZHYAZuZRcPJBdUJ1xNHMCWyPZ4p2/Yk0Q0ujdKJbJw9NFysikZgBFNEhNXEA4w8HL1ycYCmZDgSUW1GsumDAKh0Brq3K8Kh2akep8YEjDMWipKgSPaNx3CVY4lf87e0oK70nK/zKGkmpWFvyMnxbkJtWmeuxmPgRZgg2lYbZXFauD1AidnQQhPULJTTV+P+Xkk9PYm3ZkIEcDnYJUmPg/D3iuwg84m2IZatFTdjiNuDAcGNKptTd54yMgohN87c3sRMiZlSY/r88u+Le3BKWJqyl7Xai7Odqz366DFgOzdPi92LnSaggKX++hy+Z04kjyfSZOUYWmiWlc38SUdeTq2v15egig2mMkSLMaUnHagk="
});
$("#codeSummaryBar").wb_expandableframe({
iframe : contextPath + '/dailytimesheet/summaryInline.jsp'
});
$("#codeSummaryBar").click(function(){$("#codeSummaryBar_expand_collapse_icon").toggleClass("collapse expand");});
$("#codeSummaryBar").click();
$("#selectionBar").wb_expandableframe({
iframe : contextPath + '/dailytimesheet/dailySelectInline.jsp',
onExpand : function() {
$(".selectionBarControl").css("visibility", "hidden");
$("#expand_collapse_icon").removeClass("expand").addClass("collapse");
},
onCollapse : function() {
$(".selectionBarControl").css("visibility", "");
$("#expand_collapse_icon").removeClass("collapse").addClass("expand");
}
});
DTS.onload();
})(jQuery);
</script>
EDIT 2:
I doubt that you might have checked the Encode in the HTTP Request.
Uncheck
Try with the regular expression ([a-zA-Z0-9+]+)
Wanting to capture a variable called scanNumber in the http response loking like this:
{"resultCode":"SUCCESS","errorCode":null,"errorMessage":null,"profile":{"fullName":"TestFirstName TestMiddleName TestLastName","memberships":[{"name":"UA Gold Partner","number":"123-456-123-123","scanNumber":"123-456-123-123"}]}}
How can I do this with a regular experssion?
The tool I am using is Gatling stress tool (with the Scala DSL)
I have tried to do it like this:
.check(jsonPath("""${scanNumber}""").saveAs("scanNr")))
But I get the error:
---- Errors --------------------------------------------------------------------
> Check extractor resolution crashed: No attribute named 'scanNu 5 (100,0%)
mber' is defined
You were close first time.
What you actually want is:
.check(jsonPath("""$..scanNumber""").saveAs("scanNr")))
or possibly:
.check(jsonPath("""$.profile.memberships[0].scanNumber""").saveAs("scanNr")))
Note that this uses jsonPath, not regular expressions. JsonPath should more reliable than regex for this.
Check out the JsonPath spec for more advanced usage.
use this regex to match this in anywhere in json:
/"scanNumber":"[^"]+"/
and if you want to match just happens in structure you said use:
/\{[^{[]+\{[^{[]+\[\{[^{[]*("scanNumber":"[^"]+")/
Since json fields may change its order you should make your regex more tolerant for those changes:
val j = """{"resultCode":"SUCCESS","errorCode":null,"errorMessage":null,"profile":{"fullName":"TestFirstName TestMiddleName TestLastName","memberships":[{"name":"UA Gold Partner","number":"123-456-123-123","scanNumber":"123-456-123-123"}]}}"""
val scanNumberRegx = """\{.*"memberships":\[\{.*"scanNumber":"([^"]*)".*""".r
val scanNumberRegx(scanNumber) = j
scanNumber //String = 123-456-123-123
This will work even if the json fields will be in different order (but of course keep the structure)
I'm trying to use a Filter to force my users to login if they want to access some pages.
So my Filter has to redirect them to an error page in there's no session.
But I don't want this to happen when they visit index.html, because they can login in the index page.
So I need an URL Pattern that matches all the pages excluding / and index.xhtml.
How can I do that? Can I use regex in my web.xml ?
EDIT:
After reading this
I thought that I can make something like :
if (!req.getRequestURI().matches("((!?index)(.*)\\.xhtml)|((.*)\\.(png|gif|jpg|css|js(\\.xhtml)?))"))
in my doFilter() method, but it still processes everything.
I'm sure that the regex works because I've tested it online and it matches the files that doesn't need to be filtered, but the content of the if is executed even for the excluded files!
EDIT 2 :
I'm trying a new way.
I've mapped the Filter to *.xhtml in my web.xml, so I don't need to exclude css, images and javascript with the regex above.
Here's the new code (into the doFilter())
if (req.getRequestURI().contains("index")) {
chain.doFilter(request, response);
} else {
if (!userManager.isLogged()) {
request.getRequestDispatcher("error.xhtml").forward(request, response);
} else {
chain.doFilter(request, response);
}
}
but it still doesn't because it calls the chain.doFilter() (in the outer if) on every page.
How can I exclude my index page from being filtered?
The web.xml URL pattern doesn't support regex. It only supports wildcard prefix (folder) and suffix (extension) matching like /faces/* and *.xhtml.
As to your concrete problem, you've apparently the index file defined as a <welcome-file> and are opening it by /. This way the request.getRequestURI() will equal to /contextpath/, not /contextpath/index.xhtml. Debug the request.getRequestURI() to learn what the filter actually retrieved.
I suggest a rewrite:
String path = request.getRequestURI().substring(request.getContextPath().length());
if (userManager.isLogged() || path.equals("/") || path.equals("/index.xhtml") || path.startsWith(ResourceHandler.RESOURCE_IDENTIFIER)) {
chain.doFilter(request, response);
} else {
request.getRequestDispatcher("/WEB-INF/error.xhtml").forward(request, response);
}
Map this filter on /*. Note that I included the ResourceHandler.RESOURCE_IDENTIFIER check so that JSF resources like <h:outputStylesheet>, <h:outputScript> and <h:graphicImage> will also be skipped, otherwise you end up with an index page without CSS/JS/images when the user is not logged in.
Note that I assume that the FacesServlet is mapped on an URL pattern of *.xhtml. Otherwise you need to alter the /index.xhtml check on path accordingly.
I have a URL validation method which works pretty well except that this url passes: "http://". I would like to ensure that the user has entered a complete url like: "http://www.stackoverflow.com".
Here is the pattern I'm currently using:
"^(https?://)"
+ "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+#)?" //user#
+ #"(([0-9]{1,3}\.){3}[0-9]{1,3}" // IP- 199.194.52.184
+ "|" // allows either IP or domain
+ #"([0-9a-z_!~*'()-]+\.)*" // tertiary domain(s)- www.
+ #"([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\." // second level domain
+ "[a-z]{2,6})" // first level domain- .com or .museum
+ "(:[0-9]{1,4})?" // port number- :80
+ "((/?)|" // a slash isn't required if there is no file name
+ "(/[0-9a-z_!~*'().;?:#&=+$,%#-]+)+/?)$"
Any help to change the above to ensure that the user enters a complete and valid url would be greatly appreciated.
Why not use a urlparsing library? Let me list out some preexisting url parsing libraries for languages:
Python: http://docs.python.org/library/urlparse.html
Perl: http://search.cpan.org/dist/URI/URI/Split.pm
Ruby: http://www.ensta.fr/~diam/ruby/online/ruby-doc-stdlib/libdoc/uri/rdoc/classes/URI.html#M001444
PHP: http://php.net/manual/en/function.parse-url.php
Java: http://download.oracle.com/javase/1.4.2/docs/api/java/net/URI.html#URI(java.lang.String)
C#: http://msdn.microsoft.com/en-us/library/system.uri.aspx
Ask if I'm missing a language.
This way, you could first parse the uri, then check to make sure that it passes your own verification rules. Here's an example in Python:
url = urlparse.urlparse(user_url)
if not (url.scheme and url.path):
raise ValueError("User did not enter a correct url!")
Since you said you were using C# on asp.net, here's an example (sorry, my c# knowledge is limited):
user_url = "http://myUrl/foo/bar";
Uri uri = new Uri(user_url);
if (uri.Scheme == Uri.UriSchemeHttp && Uri.IsWellFormedUriString(user_url, UriKind.RelativeOrAbsolute)) {
Console.WriteLine("I have a valid URL!");
}
This is pretty much a FAQ. You could simply try a search with [regex] +validate +url or just look at this answer: What is the best regular expression to check if a string is a valid URL
I use this regex. It works fine for me.
/((([A-Za-z]{3,9}:(?://)?)(?:[-;:&=+\$,\w]+#)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+\$,\w]+#)[A-Za-z0-9.-]+)((?:/[+~%/.\w-]*)?\??(?:[-+=&;%#.\w])#?(?:[\w]))?)/
I'm using selenium RC and I would like, for example, to get all the links elements with attribute href that match:
http://[^/]*\d+com
I would like to use:
sel.get_attribute( '//a[regx:match(#href, "http://[^/]*\d+.com")]/#name' )
which would return a list of the name attribute of all the links that match the regex.
(or something like it)
thanks
The answer above is probably the right way to find ALL of the links that match a regex, but I thought it'd also be helpful to answer the other part of the question, how to use regex in Xpath locators. You need to use the regex matches() function, like this:
xpath=//div[matches(#id,'che.*boxes')]
(this, of course, would click the div with 'id=checkboxes', or 'id=cheANYTHINGHEREboxes')
Be aware, though, that the matches function is not supported by all native browser implementations of Xpath (most conspicuously, using this in FF3 will throw an error: invalid xpath[2]).
If you have trouble with your particular browser (as I did with FF3), try using Selenium's allowNativeXpath("false") to switch over to the JavaScript Xpath interpreter. It'll be slower, but it does seem to work with more Xpath functions, including 'matches' and 'ends-with'. :)
You can use the Selenium command getAllLinks to get an array of the ids of links on the page, which you could then loop through and check the href using the getAttribute, which takes the locator followed by an # and the attribute name. For example in Java this might be:
String[] allLinks = session().getAllLinks();
List<String> matchingLinks = new ArrayList<String>();
for (String linkId : allLinks) {
String linkHref = selenium.getAttribute("id=" + linkId + "#href");
if (linkHref.matches("http://[^/]*\\d+.com")) {
matchingLinks.add(link);
}
}
A possible solution is to use sel.get_eval() and write a JS script that returns a list of the links. something like the following answer:
selenium: Is it possible to use the regexp in selenium locators
Here's some alternate methods as well for Selenium RC. These aren't pure Selenium solutions, they allow interaction with your programming language data structures and Selenium.
You can also get get HTML page source, then regular expression the source to return a match set of links. Use regex grouping to separate out URLs, link text/ID, etc. and you can then pass them back to selenium to click on or navigate to.
Another method is get HTML page source or innerHTML (via DOM locators) of a parent/root element then convert the HTML to XML as DOM object in your programming language. You can then traverse the DOM with desired XPath (with regular expression or not), and obtain a nodeset of only the links of interest. From their parse out the link text/ID or URL and you can pass back to selenium to click on or navigate to.
Upon request, I'm providing examples below. It's mixed languages since the post didn't appear to be language specific anyways. I'm just using what I had available to hack together for examples. They aren't fully tested or tested at all, but I've worked with bits of the code before in other projects, so these are proof of concept code examples of how you'd implement the solutions I just mentioned.
//Example of element attribute processing by page source and regex (in PHP)
$pgSrc = $sel->getPageSource();
//simple hyperlink extraction via regex below, replace with better regex pattern as desired
preg_match_all("/<a.+href=\"(.+)\"/",$pgSrc,$matches,PREG_PATTERN_ORDER);
//$matches is a 2D array, $matches[0] is array of whole string matched, $matches[1] is array of what's in parenthesis
//you either get an array of all matched link URL values in parenthesis capture group or an empty array
$links = count($matches) >= 2 ? $matches[1] : array();
//now do as you wish, iterating over all link URLs
//NOTE: these are URLs only, not actual hyperlink elements
//Example of XML DOM parsing with Selenium RC (in Java)
String locator = "id=someElement";
String htmlSrcSubset = sel.getEval("this.browserbot.findElement(\""+locator+"\").innerHTML");
//using JSoup XML parser library for Java, see jsoup.org
Document doc = Jsoup.parse(htmlSrcSubset);
/* once you have this document object, can then manipulate & traverse
it as an XML/HTML node tree. I'm not going to go into details on this
as you'd need to know XML DOM traversal and XPath (not just for finding locators).
But this tutorial URL will give you some ideas:
http://jsoup.org/cookbook/extracting-data/dom-navigation
the example there seems to indicate first getting the element/node defined
by content tag within the "document" or source, then from there get all
hyperlink elements/nodes and then traverse that as a list/array, doing
whatever you want with an object oriented approach for each element in
the array. Each element is an XML node with properties. If you study it,
you'd find this approach gives you the power/access that WebDriver/Selenium 2
now gives you with WebElements but the example here is what you can do in
Selenium RC to get similar WebElement kind of capability
*/
Selenium's By.Id and By.CssSelector methods do not support Regex and By.XPath only does where XPath 2.0 is enabled. If you want to use Regex, you can do something like this:
void MyCallingMethod(IWebDriver driver)
{
//Search by ID:
string attrName = "id";
//Regex = 'a number that is 1-10 digits long'
string attrRegex= "[0-9]{1,10}";
SearchByAttribute(driver, attrName, attrRegex);
}
IEnumerable<IWebElement> SearchByAttribute(IWebDriver driver, string attrName, string attrRegex)
{
List<IWebElement> elements = new List<IWebElement>();
//Allows spaces around equal sign. Ex: id = 55
string searchString = attrName +"\\s*=\\s*\"" + attrRegex +"\"";
//Search page source
MatchCollection matches = Regex.Matches(driver.PageSource, searchString, RegexOptions.IgnoreCase);
//iterate over matches
foreach (Match match in matches)
{
//Get exact attribute value
Match innerMatch = Regex.Match(match.Value, attrRegex);
cssSelector = "[" + attrName + "=" + attrRegex + "]";
//Find element by exact attribute value
elements.Add(driver.FindElement(By.CssSelector(cssSelector)));
}
return elements;
}
Note: this code is untested. Also, you can optimize this method by figuring out a way to eliminate the second search.