Tuesday, January 4, 2011

PRACTICUM: Selenium 1.0 Testing Tools: Chapter 3: Pattern Matching

This is the third entry for the TESTHEAD PRACTICUM review of PACKT Publishing's book Selenium 1.0 Testing Tools Beginners Guide by David Burns. The emphasis on this type of review continues to be the actual exercises and the practical applications of what we learn. Rather than reprint out the full listing of the exercises in the book (and there are a bunch of them, as that is the format of this particular title), much of these chapters are going to be a summary of the content, some walk-through of application, and my take on what I see and do.


Selenium 1.0 Testing Tools is full of examples, "try it yourself" instructions and explanations of what happened. The book’s cover states “Learn by doing: less theory, more results”. The focus will be less on the concepts and more on the actual implementation and methods suggested. Note also that copying and pasting screenshots of the Selenium IDE is somewhat redundant, as the log output lines up with the table values for each of the sections. To make examples simpler to follow, though, I've appended a number of commands with  (Command: commandName, Target: targetName, Value: valueName)


Chapter 3: Pattern Matching


Text is key to being able to make sure that we have what we think we do, and that the values we expect to be there are there. It's also critical when we try to anticipate what should be there when we create asserts for items that need to be there when content is dynamically generated (AJAX, etc.).


Chapter 3 focuses on using regular expressions and globs for verifying text patterns. Verify and assert statements depend on this functionality.


This chapter's focus is to:

  • Make sure text is exact in elements
  • Use globs to verify text
  • Use regular expressions


Verifying Exact Text


In many instances, having an exact match for text is important for tests. The prefix "exact:" is what is used to designate that a text string needs to be an exact match. Let's examine pages that are generated dynamically according to the path. We'll use the exact: prefix to check that the exact text is in the element on the page.


1. Navigate to http://book.theautomatedtester.co.uk/chapter3/yourname
where yourname in the URL has been replaced (I've used 'MichaelLarsen").
2. Verify that the div with the ID name contains your name exactly.
3. Run your test.


Example Successful Log output below (remember that the Selenese that follows [info] represents |Command|Target|Value|):


[info] Executing: |open | /chapter3/MichaelLarsen | |
[info] Executing: |verifyText | name | exact:MichaelLarsen |



Now let's make a change by removing some characters from the expected value ("MichaeLarse"), and let's see what happens:


[info] Executing: |open | /chapter3/MichaelLarsen |
[info] Executing: |verifyText | name | exact:MichaeLarse |
[error] Actual value 'MichaelLarsen' did not match 'exact:MichaeLarse' 



When we use "exact:", tht's what it expects. Missing characters will trigger an error, but differences in capitalization will also trigger errors (substitute 'michaellarsen'):


[info] Executing: |open | /chapter3/MichaelLarsen | |
[info] Executing: |verifyText | name | exact:michaellarsen |
[error] Actual value 'MichaelLarsen' did not match 'exact:michaellarsen'




exact: can also be used with links. This helps to confirm the link exists (exactly as expected) and to
click on it. Doing this saves us the extra step of  first having to verify the link.


1. Open http://book.theautomatedtester.co.uk/chapter3/yourname
where yourname is your name (Command: open, Target: /chapter3/MichaelLarsen).
2. Click on the link Index, but make sure you add the exact: prefix (Command: click, Target: link=exact:Index  .
3. Run your test.


Here's a sample output:


[info] Executing: |open | /chapter3/MichaelLarsen |
[info] Executing: |click | link=exact:Index | | 


Using Globs in Tests


Exact matches are a nice thing to use, but what if in your dynamically generated pages, you can't count on an exact match for a div value? A limited syntax technique called "globbing" can be used. Don't let the limited syntax part fool you; globs are used extensively in Selenium as a pattern matching method.


The book demonstrates an example on the chapter3 page where the user's zodiac sign and current date can be displayed. In this case, the zodiac symbol is the data that matters. The verifyTextPresent call will
be used to apply the glob to the entire page.


1. Open up the Selenium IDE.
2. Navigate to http://book.theautomatedtester.co.uk/chapter3 (Command: open, Target: /chapter3).
3. Using verifyTextPresent, confirm "Virgo" is on the page (Command: verifyTextPresent, Target: Virgo).
4. Run the test. 

Log output:


[info] Executing: |open | /chapter3 | |
[info] Executing: |verifyTextPresent | Virgo | |


Globs are useful for confirming an element exists, regardless of where it is on the page. Standard disclaimer, No Purchase Necessary, Void Where Prohibited, etc. text can be verified with this technique if it exists. The inverse call, verifyTextNotPresent, verifies that the text in question is not on the page.


Globs have limited regular expression style syntax rules that can be used. If we wanted to search for just the word fragment Vir and didn't care about what followed afterwards, we could use "Vir*" (check for "Vir" and anything else that follows after it). 


Example:


1. Open up the Selenium IDE.
2. Navigate to http://book.theautomatedtester.co.uk/chapter3 (Command: open, Target: /chapter3).
3. Using verifyText, check that UI-Element 'divinthecenter' has "Vir" in it (Command: verifyText, Target: divinthecenter, Value: glob:Vir*  ).
4. Run the test. 


Log Output:


[info] Executing: |open | /chapter3 | |
[info] Executing: |verifyText | divinthecenter | glob:Vir* |

If you want to just check for a one character difference, you can use the '?' wild card to check just one character. 

1. Open up the Selenium IDE.
2. Navigate to http://book.theautomatedtester.co.uk/chapter3 (Command: open, Target: /chapter3).
3. Using verifyText, check to see that leftdiv matches ?ool (Command: verifyText, Target: leftdiv, Value: glob:?ool)
4. Run the test


Log Output:


[info] Executing: |open | /chapter3 | |
[info] Executing: |verifyText | leftdiv | glob:?ool | 


Character classes can also be used to allow for a range of characters.
Follow the same steps as above, but change the glob option to be a range of characters with c, f, m, and p as valid choices.Using verifyTextpresent, check to see that the page contains [cfpm]ool (Command: verifyTextPresent, Target: glob:[cfmp]ool).

Run the test.


Log Output (interestingly, we receive an error when we try to run this with Selenium IDE 1.0.10):


[info] Executing: |open | /chapter3||
[info] Executing: |verifyTextPresent | glob:[cfmp]ool| 
[error] false 


Using Regular Expressions


Globbing patterns have a limitation, they can't check a field to see if it has numbers, or ignoring letter case. To expand on globbing and provide additional ability to see text patterns and include numbers and text, we need to use the regular expression option. This is done by putting 'regexp:' in front of the string we are looking at. If we want to use regular expressions to check the date and that it is formatted a certain way, we can.


Example date format on the Chapter 3 page:  Wed 05 Jan 2011

Let's check that the date follows this pattern:

Three letters for the day, two numbers for the day of the month, three letters for the month, and
four numbers for the year. The regular expression for this would be:

 \w{3} \d{2} \w{3} \d{4}

The \w looks for word characters, the \d looks for digit characters. Curly braces for each value represent how many values to expect for each type.

Create a command where verifyText in the div with the ID centerdiv with the Value field populated
regexp:\w{3} \d{2} \w{3} \d{4} (Command: verifyText, Target: centerdiv, Value: regexp:\w{3} \d{2} \w{3} \d{4}).


Log Output:


[info] Executing: |open | /chapter3 | |
[info] Executing: |verifyText | centerdiv | regexp:\w{3} \d{2} \w{3} \d{4} | 

Regular expression wild cards allow for more flexibility than the glob examples. Here are some examples. 

The . (dot) operator, followed  by '*'  tells the regular expression that there will be instances between "0" and "n" of an element, while the (dot) operator followed by  '+' tells the regular expression that there will be instances between "1" and "n" of an element.


1. Open the Selenium IDE.
2. Navigate to http://book.theautomatedtester.co.uk/chapter3/yourname
where yourname is replaced by your name. (Command: open, Target: /chapter3/MichaelLarsen)
3. Note verifyText in the div with the ID name. Match either letters or numbers
and add the wild card such as \w.*. (Command: verifyText, Target: name, Value: regexp:\w.*).
4. Run the test.

Log Output:


[info] Executing: |open | /chapter3/MichaelLarsen | |
[info] Executing: |verifyText | name | regexp:\w.* | 


Switch out the value so that it uses the '+':


Log Output:


[info] Executing: |open | /chapter3/MichaelLarsen |
[info] Executing: |verifyText | name | regexp:\w.+ | 


Selenium also supports the range option of [A-Za-z] and other values common to regular expression syntax (do searches of check books on regular expressions for more examples.


Log Output:


[info] Executing: |open | /chapter3/MichaelLarsen | |
[info] Executing: |verifyText | name | regexp:\w.[A-Za-z0-9] | 


When we look for text values we can go from extremely specific to super general.

Exact Pattern Matching: Make sure elements match exactly the text values we specify.

Globbing Patterns: Uses basic patterns similar to how the DOS and UNIX command prompt uses them to make sure text on the page matches an expected value.

Regular Expressions: More robust options to search and compare to a pattern. 

No comments: