Skip to end of metadata
Go to start of metadata

Use spinAsserts

One issue with Selenium is that it doesn't know when it's supposed to wait before executing the next command. When people click a submit button, they know not to check for text or try another action until the next page loads. Selenium, however, immediately executes the next command. If the next command is part of an assertion in your code the assertion may fail, even though if Selenium had waited a little bit longer it would have succeeded.

The solution is to use a special kind of assertion called a spinAssert that was introduced earlier in this tutorial. This kind of assertion only fails after retrying periodically over a specified amount of time.

The definition of the spinAssert function in Sausage looks like this:

php <?php public function spinAssert($msg, $test, $args=array(), $timeout=10)

  • $msg is the message that's passed to the Exception if the spinAssert fails.
  • $test is the function we are going to use for the assertion. It can be:
    • An anonymous function
    • A string representing a function name
    • An array of the form array($class_name, $method_name)
  • $args is an array of arguments that's passed to the test function.
  • $timeout is an integer representing the number of seconds to spin.

The spinAssert function calls the $test function once every second until the $timeout seconds limit is reached. If the $test function returns a true value the assertion succeeds If the $test function returns a false value the test is retried every second until it hits $timeout seconds. If it hits $timeout seconds the assertion fails.

If spinAssert example earlier in the tutorial didn't have a spinAssert it would have looked like this:

php <?php public function testSubmitComments() { $comment = "This is a very insightful comment."; $this->byId('comments')->click(); $this->keys($comment); $this->byId('submit')->submit(); $this->assertEquals($this->byId('your_comments')->text(), "Your comments: $comment"); }

The trouble with this is that after Selenium hits the submit button it immediately gets the text from the comment results box (the element id #your_comments). If the page didn't have time to get updated from the server the assertion fails even though it would have succeeded if Selenium had waited a bit longer.

Let's look at the same function using spinAssert:

```php <?php public function testSubmitComments() { $comment = "This is a very insightful comment."; $this->byId('comments')->click(); $this->keys($comment); $this->byId('submit')->submit(); $driver = $this;

$comment_test =
    function() use ($comment, $driver)
        return ($driver->byId('your_comments')->text() == "Your comments: $comment");

$this->spinAssert("Comment never showed up!", $comment_test);

} ```

In this function, we create an anonymous closure called $comment_test that returns true if the comments field has the right text in it and false if it doesn't. Then we call $this->spinAssert and pass it the test function. We're using the default timeout of 10 seconds, so our script keeps retrying the Selenium text() command until its value is what we expect or we hit 10 seconds.

Using spinAssert functions is a great way to make tests less brittle and more accepting of differences in network speeds, surges in traffic, and other challenges in the test environment.

  • No labels