Here are a few snippets of how I’ve achieved various tasks, some tricks and patterns\u00a0in phpunit\/phpunit-selenium v2.0 – targeting Selenium2. I’ll try to keep this updated with more techniques over time.<\/p>\n
Screenshots<\/strong><\/p>\n I wrote this small hook\u00a0to make screenshots automatic, like they used to be. Of course you may want to put a timestamp in the file, but I usually only\u00a0want the last problem.<\/p>\n Waiting for stuff<\/strong><\/p>\n An eternal issue in automated testing is latency and timeouts. Particularly problematic in anything other than a standard onclick-pageload cycle, such as pop-up calendars or a JS app. Again I felt the move from Selenium1 to 2 made this much more clumsy, so I wrote this simple wrapper for the common wait pattern boilerplate.<\/p>\n Checking for the right page, reliably.<\/strong><\/p>\n If something goes wrong in a complex test\u00a0with lots of interactions, it’s important to fail fast<\/em> \u00a0– for example if the wrong page loads, nothing else will work very well. So I always check the page being tested is the right page<\/em>.\u00a0To do this reliably, not using content or design-specific elements, I add a <body> tag “id” attribute to every page (you could use body class if you’re already using that styling technique but I tend to separate my QA tagging from CSS dependencies). Then I added this assertion\u00a0to my base test case.<\/p>\n Getting Value<\/strong><\/p>\n The ->value() method was\u00a0removed in Selenium v2.42.0. The replacement method\u00a0is to use $element->attribute(‘value’) [source<\/a>]<\/p>\n However ->value() was also a mutator (setter), which ->attribute() is not. So if you want to update<\/em> a value, people say<\/a>\u00a0you have to resort to injecting JavaScript into the page, which I found somewhat distasteful. However luckily this is not the case for the “value” attribute specifically,\u00a0according to the source code, it’s only the GET<\/span> which was removed from ->value().<\/p>\n JSON Wire Protocol only supports POST to \/value now. To get the value of an element GET \/attribute\/:naem should be used<\/p><\/blockquote>\n So I\u00a0can carry on doing this, presumably until the next update breaks everything.<\/p>\n General Page Tests<\/strong><\/p>\n I have one test suite that just whips through a list of all known pages on a site and scans them for errors, a visual regression smoke test for really stupid\u00a0errors. It’s also easy to drop a call to this method in at the beginning of any test. When I spot other visual errors occurring, I can add them to the list.<\/p>\n <\/p>\n","protected":false},"excerpt":{"rendered":" My PHPUnit-Selenium2 Cheat Sheet Here are a few snippets of how I’ve achieved various tasks, some tricks and patterns\u00a0in phpunit\/phpunit-selenium v2.0 – targeting Selenium2. I’ll try to keep this updated with more techniques over time. Screenshots I wrote this small … Continue reading \/**\r\n * PhpUnitSelenium v1 used to have automatic screenshot as a feature, in v2 you have to do it \"manually\".\r\n *\/\r\npublic function onNotSuccessfulTest(Exception $e){\r\n file_put_contents(__DIR__.'\/..\/..\/out\/screenshots\/screenshot1.png', $this->currentScreenshot());\r\n\r\n parent::onNotSuccessfulTest($e);\r\n}\r\n<\/pre>\n\/**\r\n * Utility method to wait for an element to appear.\r\n *\r\n * @param string $selector\r\n * @param int $timeout milliseconds wait cap, after which you'll get an error\r\n *\/\r\nprotected function waitFor($selector, $timeout=self::WAIT_TIMEOUT_MS){\r\n $this->waitUntil(function(PHPUnit_Extensions_Selenium2TestCase $testCase) use($selector){\r\n try {\r\n $testCase->byCssSelector($selector);\r\n } catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {\r\n return null;\r\n }\r\n return true;\r\n }, $timeout);\r\n}\r\n\r\n<\/pre>\n\/**\r\n * We use <body id=\"XXX\"> to identify pages reliably.\r\n * @param $id\r\n *\/\r\nprotected function assertBodyIDEquals($id){\r\n $this->assertEquals($id, $this->byCssSelector('body')->attribute('id'));\r\n}<\/pre>\n\/\/ old way\r\n\/\/$sCurrentStimulus = $this->byName('word_index')->value();\r\n\/\/ new way\r\n$sCurrentStimulus = $this->byName('word_index')->attribute('value');\r\n\/\/ I actually use this now:\r\n$sCurrentStimulus = $this->byCssSelector('input[name=word_index]')->attribute('value');<\/pre>\n$this->byName('u_first_name')->value(GeneralFixtures::VAlID_SUBJECT_USERNAME);\r\n\r\n\r\n<\/pre>\n\/**\r\n * Looks for in-page errors.\r\n *\/\r\nprotected function checkErrors() {\r\n $txt = $this->byTag('body')->text();\r\n $src = $this->source();\r\n\r\n \/\/ Removed: This false-positives on the news page.\r\n \/\/$this->assertNotContains('error', $this->byTag('body')->text());\r\n\r\n \/\/ Standard CI errors\r\n $this->assertNotContains('A Database Error Occurred', $txt);\r\n $this->assertNotContains('404 Page Not Found', $txt);\r\n $this->assertNotContains('An Error Was Encountered', $txt);\r\n \/\/ PHP errors\r\n $this->assertNotContains('Fatal error: :', $txt);\r\n $this->assertNotContains('Parse error:', $txt);\r\n\r\n \/\/ the source might have hidden errors, but then it also might contain the word error? false positive?\r\n \/\/ This false positives in the user form (must have validation error text!\r\n \/\/$this->assertNotContains('error', $this->source());\r\n $this->assertNotContains('xdebug-error', $src); \/\/ XDebug wrapper class\r\n\r\n}<\/pre>\n