{"id":405,"date":"2016-06-29T12:59:08","date_gmt":"2016-06-29T01:59:08","guid":{"rendered":"http:\/\/scipilot.org\/blog\/?p=405"},"modified":"2016-06-29T12:59:08","modified_gmt":"2016-06-29T01:59:08","slug":"phpunit-selenium2-cheat-sheet","status":"publish","type":"post","link":"https:\/\/scipilot.org\/blog\/2016\/06\/29\/phpunit-selenium2-cheat-sheet\/","title":{"rendered":"PHPUnit-Selenium2 Cheat Sheet"},"content":{"rendered":"<h1><strong>My PHPUnit-Selenium2 Cheat Sheet<\/strong><\/h1>\n<p>Here are a few snippets of how I&#8217;ve achieved various tasks, some tricks and patterns\u00a0in phpunit\/phpunit-selenium v2.0 &#8211; targeting Selenium2. I&#8217;ll try to keep this updated with more techniques over time.<\/p>\n<p><strong>Screenshots<\/strong><\/p>\n<p>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<pre>\/**\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-&gt;currentScreenshot());\r\n\r\n parent::onNotSuccessfulTest($e);\r\n}\r\n<\/pre>\n<p><strong>Waiting for stuff<\/strong><\/p>\n<p>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<pre>\/**\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-&gt;waitUntil(function(PHPUnit_Extensions_Selenium2TestCase $testCase) use($selector){\r\n  try {\r\n   $testCase-&gt;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<p><strong>Checking for the right page, reliably.<\/strong><\/p>\n<p>If something goes wrong in a complex test\u00a0with lots of interactions, it&#8217;s important to <em>fail fast<\/em> \u00a0&#8211; for example if the wrong page loads, nothing else will work very well. So I always check the page being tested <em>is the right page<\/em>.\u00a0To do this reliably, not using content or design-specific elements, I add a &lt;body&gt; tag &#8220;id&#8221; attribute to every page (you could use body class if you&#8217;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<pre>\/**\r\n * We use &lt;body id=\"XXX\"&gt; to identify pages reliably.\r\n * @param $id\r\n *\/\r\nprotected function assertBodyIDEquals($id){\r\n $this-&gt;assertEquals($id, $this-&gt;byCssSelector('body')-&gt;attribute('id'));\r\n}<\/pre>\n<p><strong>Getting Value<\/strong><\/p>\n<p>The -&gt;value() method was\u00a0removed in Selenium v2.42.0. The replacement method\u00a0is to use $element-&gt;attribute(&#8216;value&#8217;) [<a href=\"http:\/\/stackoverflow.com\/a\/24635568\/209288\">source<\/a>]<\/p>\n<pre>\/\/ old way\r\n\/\/$sCurrentStimulus = $this-&gt;byName('word_index')-&gt;value();\r\n\/\/ new way\r\n$sCurrentStimulus = $this-&gt;byName('word_index')-&gt;attribute('value');\r\n\/\/ I actually use this now:\r\n$sCurrentStimulus = $this-&gt;byCssSelector('input[name=word_index]')-&gt;attribute('value');<\/pre>\n<p>However -&gt;value() was also a mutator (setter), which -&gt;attribute() is not. So if you want to <em>update<\/em> a value, <a href=\"http:\/\/stackoverflow.com\/a\/27623506\/209288\">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 &#8220;value&#8221; attribute specifically,\u00a0according to the source code, it&#8217;s <span style=\"text-decoration: underline;\">only the GET<\/span> which was removed from -&gt;value().<\/p>\n<blockquote><p>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<p>So I\u00a0can carry on doing this, presumably until the next update breaks everything.<\/p>\n<pre>$this-&gt;byName('u_first_name')-&gt;value(GeneralFixtures::VAlID_SUBJECT_USERNAME);\r\n\r\n\r\n<\/pre>\n<p><strong>General Page Tests<\/strong><\/p>\n<p>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&#8217;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<pre>\/**\r\n * Looks for in-page errors.\r\n *\/\r\nprotected function checkErrors() {\r\n $txt = $this-&gt;byTag('body')-&gt;text();\r\n $src = $this-&gt;source();\r\n\r\n \/\/ Removed: This false-positives on the news page.\r\n \/\/$this-&gt;assertNotContains('error', $this-&gt;byTag('body')-&gt;text());\r\n\r\n \/\/ Standard CI errors\r\n $this-&gt;assertNotContains('A Database Error Occurred', $txt);\r\n $this-&gt;assertNotContains('404 Page Not Found', $txt);\r\n $this-&gt;assertNotContains('An Error Was Encountered', $txt);\r\n \/\/ PHP errors\r\n $this-&gt;assertNotContains('Fatal error: :', $txt);\r\n $this-&gt;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-&gt;assertNotContains('error', $this-&gt;source());\r\n $this-&gt;assertNotContains('xdebug-error', $src); \/\/ XDebug wrapper class\r\n\r\n}<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My PHPUnit-Selenium2 Cheat Sheet Here are a few snippets of how I&#8217;ve achieved various tasks, some tricks and patterns\u00a0in phpunit\/phpunit-selenium v2.0 &#8211; targeting Selenium2. I&#8217;ll try to keep this updated with more techniques over time. Screenshots I wrote this small &hellip; <a href=\"https:\/\/scipilot.org\/blog\/2016\/06\/29\/phpunit-selenium2-cheat-sheet\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[26,36,65,12],"class_list":["post-405","post","type-post","status-publish","format-standard","hentry","category-articles","tag-php","tag-programming","tag-qa","tag-unit-testing"],"_links":{"self":[{"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/posts\/405","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/comments?post=405"}],"version-history":[{"count":1,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/posts\/405\/revisions"}],"predecessor-version":[{"id":406,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/posts\/405\/revisions\/406"}],"wp:attachment":[{"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/media?parent=405"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/categories?post=405"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/tags?post=405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}