{"id":282,"date":"2015-03-19T12:36:34","date_gmt":"2015-03-19T10:36:34","guid":{"rendered":"https:\/\/schwarzer.de\/blog\/?p=282"},"modified":"2020-09-17T15:41:29","modified_gmt":"2020-09-17T13:41:29","slug":"tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid","status":"publish","type":"post","link":"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/","title":{"rendered":"Selenium Tutorial deutsch: Testen von dynamischen Webapplikationen mit PHP und Selenium Grid"},"content":{"rendered":"<p><!-- <ezTOC> -->  <\/p>\n<style type=\"text\/css\">code{white-space: pre;font-size:12px;line-height:100%;}<\/style>\n<style type=\"text\/css\">\ntable.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {\n  margin: 0; padding: 0; vertical-align: baseline; border: none; }\ntable.sourceCode { width: 100%; line-height: 100%; }\ntd.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }\ntd.sourceCode { padding-left: 5px; }\ncode > span.kw { color: #007020; font-weight: bold; }\ncode > span.dt { color: #902000; }\ncode > span.dv { color: #40a070; }\ncode > span.bn { color: #40a070; }\ncode > span.fl { color: #40a070; }\ncode > span.ch { color: #4070a0; }\ncode > span.st { color: #4070a0; }\ncode > span.co { color: #60a0b0; font-style: italic; }\ncode > span.ot { color: #007020; }\ncode > span.al { color: #ff0000; font-weight: bold; }\ncode > span.fu { color: #06287e; }\ncode > span.er { color: #ff0000; font-weight: bold; }\n  <\/style>\n<p>Nachdem wir <strong><a href=\"\/blog\/automatisiertes-testen-funktioniert-selenium-grid\/\">die Architektur von Selenium Grid verstanden<\/a><\/strong> und unseren <strong><a href=\"\/blog\/selenium-grid-installieren-und-konfigurieren\/\">ersten Selenium Hub und Node gestartet<\/a><\/strong> haben ist es nun an der Zeit, das erste PHP-Testscript zu schreiben.<\/p>\n<ul>\n<li><a href=\"#selenium-und-php-testen-testfall\">Selenium und PHP testen: Testfall<\/a><\/li>\n<li><a href=\"#tutorial-php-und-selenium-grid-step-by-step\">Tutorial PHP und Selenium Grid: Step by Step<\/a>\n<ul>\n<li><a href=\"#einstellungen-im-php-code-vornehmen\">Einstellungen im PHP-Code vornehmen<\/a>\n<ul>\n<li><a href=\"#testen-bei-browserstack.com\">Testen bei Browserstack.com<\/a><\/li>\n<li><a href=\"#opera-28-und-chrome-in-einem-grid\">Opera 28 und Chrome in einem Grid<\/a>\n<ul>\n<li><a href=\"#operachromiumdriver-starten-des-opera-nodes\">OperaChromiumDriver: Starten des Opera-Nodes<\/a><\/li>\n<li><a href=\"#operachromiumdriver-chrome-als-desiredcapabilities-angeben\">OperaChromiumDriver: <code>chrome<\/code> als DesiredCapabilities angeben<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#aufrufen-der-startseite\">Aufrufen der Startseite<\/a>\n<ul>\n<li><a href=\"#ansprechen-von-objekten\">Ansprechen von Objekten<\/a><\/li>\n<li><a href=\"#kleines-helferlein-firepath\">Kleines Helferlein: Firepath<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#ladezeiten-\u00fcberbr\u00fccken\">Ladezeiten \u00fcberbr\u00fccken<\/a>\n<ul>\n<li><a href=\"#php-sleep-methode\">PHP-sleep()-Methode<\/a><\/li>\n<li><a href=\"#warten-auf-existenz-eines-objekts\">Warten auf Existenz eines Objekts<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#auf-ausf\u00fchrung-von-ajax-warten\">Auf Ausf\u00fchrung von AJAX warten<\/a><\/li>\n<li><a href=\"#pr\u00fcfen-des-inhalts-eines-elements\">Pr\u00fcfen des Inhalts eines Elements<\/a><\/li>\n<li><a href=\"#screenshot-erstellen\">Screenshot erstellen<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#schlusswort-automated-website-testing-lohnt-sich\">Schlusswort: Automated Website-Testing lohnt sich<\/a><\/li>\n<\/ul>\n<h2 id=\"selenium-und-php-testen-testfall\">Selenium Tutorial deutsch: Testfall<\/h2>\n<p>Das <strong>Testen unserer dynamischen Webanwendung<\/strong> soll folgendes beinhalten:<\/p>\n<ul>\n<li>Aufrufen der Startseite<\/li>\n<li>Warten, bis die Seite geladen ist<\/li>\n<li>Anklicken eines Links, welcher <strong>AJAX triggert<\/strong><\/li>\n<li><strong>Warten auf die Ausf\u00fchrung<\/strong> von AJAX<\/li>\n<li>Pr\u00fcfen des Inhalts eines bestimmten Elements<\/li>\n<li>Bei fehlerhaftem Inhalt einen <strong>Screenshot erstellen<\/strong>\n<figure id=\"attachment_284\" aria-describedby=\"caption-attachment-284\" style=\"width: 121px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-schematische-darstellung-eines-beispieltests-mit-selenium-grid-webdriver.png\"><img src=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-schematische-darstellung-eines-beispieltests-mit-selenium-grid-webdriver-121x300.png\" alt=\"Infografik #1: Schematische Darstellung eines Beispieltests mit Selenium Grid\/Webdriver\" width=\"121\" height=\"300\" class=\"size-medium wp-image-284\" \/><\/a><figcaption id=\"caption-attachment-284\" class=\"wp-caption-text\">Infografik #1: Schematische Darstellung eines Beispieltests mit Selenium Grid\/Webdriver<\/figcaption><\/figure>\n<p>Als Testobjekt nehmen wir eine mit AJAX-lastige Seite unseres Kunden: <em>budenheim.com<\/em>. Dort werden z.B. beim Klicken auf die meisten Links nicht wie gewohnt <em>neue<\/em> Seiten geladen, sondern der Inhalt dieser Seiten via <strong>asynchronem JavaScript<\/strong> nachgeladen. Da k\u00f6nnen wir uns austoben!<\/p>\n<h2 id=\"tutorial-php-und-selenium-grid-step-by-step\">Selenium Tutorial PHP und Selenium Grid: Step by Step<\/h2>\n<h3 id=\"einstellungen-im-php-code-vornehmen\">Einstellungen im PHP-Code vornehmen<\/h3>\n<p>In <a href=\"\/blog\/selenium-grid-installieren-und-konfigurieren\/\">dem vorherigen Artikel<\/a> wurde bereits gezeigt, wie man die f\u00fcr PHP n\u00f6tigen Selenium-Bibliotheken installiert, um damit vern\u00fcnftig arbeiten zu k\u00f6nnen. Wenn das geschehen ist, kann man diese wie folgt in sein PHP-Script einbinden:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">require_once<\/span> <span class=\"ot\">(<\/span><span class=\"st\">'php-webdriver\/lib\/__init__.php'<\/span><span class=\"ot\">);<\/span>\r\n<span class=\"fu\">echo<\/span> <span class=\"st\">\"Website-Check 1.0<\/span><span class=\"kw\">\\n<\/span><span class=\"st\">\"<\/span><span class=\"ot\">;<\/span><\/code><\/pre>\n<p>Und wenn wir uns schon mal im Header des Quellcodes befinden, schreiben wir gleich fest, wie unser Hub zu erreichen ist:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$host<\/span> = <span class=\"st\">'http:\/\/swuser-xubuntu:4444\/wd\/hub'<\/span><span class=\"ot\">;<\/span><\/code><\/pre>\n<p>Wobei f\u00fcr den URL dieses Schema angewendet wird:<\/p>\n<pre><code>http:\/\/{Hub-Hostname\/IP}:{Hub-Port}\/wd\/hub<\/code><\/pre>\n<p>Jetzt definieren wir einen Browser, den wir dann im Selenium Grid steuern k\u00f6nnen. Nehmen wir in unserem Beispiel Google Chrome, der auf den bereits laufenden Node zeigt.<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$chrome<\/span> = DesiredCapabilities::chrome <span class=\"ot\">(<\/span> <span class=\"ot\">);<\/span><\/code><\/pre>\n<p>Das gleiche Prinzip kann man auch f\u00fcr andere Browser anwenden:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$firefox<\/span> = DesiredCapabilities::firefox <span class=\"ot\">(<\/span> <span class=\"ot\">);<\/span>\r\n<span class=\"kw\">$ie<\/span> = DesiredCapabilities::internetExplorer <span class=\"ot\">(<\/span> <span class=\"ot\">);<\/span><\/code><\/pre>\n<p>Diese Angaben kann man noch etwas n\u00e4her spezifizieren, um z.B. eine <strong>bestimmte Version unter einem bestimmten Betriebssystem<\/strong> anzusprechen:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$chrome<\/span> = DesiredCapabilities::chrome <span class=\"ot\">(<\/span> <span class=\"ot\">);<\/span>\r\n<span class=\"kw\">$chrome<\/span> -&gt; setPlatform <span class=\"ot\">(<\/span> <span class=\"st\">'WINDOWS'<\/span> <span class=\"ot\">);<\/span>\r\n<span class=\"kw\">$chrome<\/span>-&gt;setVersion<span class=\"ot\">(<\/span><span class=\"st\">'40.0'<\/span><span class=\"ot\">);<\/span><\/code><\/pre>\n<p>Die Angaben h\u00e4ngen direkt mit den Parametern im Ausf\u00fchrungsbefehl des Nodes zusammen. Wenn man einen Selenium Node mit Google Chrome wie folgt gestartet hat &#8230;<\/p>\n<pre><code>java -jar C:\/selenium\/selenium-server-standalone-2.44.0.jar \\\r\n -role webdriver \\\r\n -hub http:\/\/swuser-xubuntu:4444\/grid\/register \\\r\n -browser browserName=chrome,maxInstances=4,*****platform=WINDOWS,version=40.0***** \\\r\n -Dwebdriver.*****chrome*****.driver=C:\/selenium\/chromedriver.exe \\\r\n -port 5556\r\n# man beachte die mit ***** hervorgehobenen Stellen<\/code><\/pre>\n<p>&#8230; kann man genau diesen Node dadurch gezielt ansprechen, indem man folgende Angaben macht:<\/p>\n<table>\n<thead>\n<tr class=\"header\">\n<th align=\"left\">Name<\/th>\n<th align=\"left\">Wert<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"odd\">\n<td align=\"left\">Browser<\/td>\n<td align=\"left\"><code>chrome<\/code><\/td>\n<\/tr>\n<tr class=\"even\">\n<td align=\"left\">Platform<\/td>\n<td align=\"left\"><code>WINDOWS<\/code><\/td>\n<\/tr>\n<tr class=\"odd\">\n<td align=\"left\">Browser-Version<\/td>\n<td align=\"left\"><code>40.0<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>So kann man z.B. in einem Selenium Grid mehrere Betriebssystem\/Browser\/Browser-Version-Kombination laufen lassen, ohne dass es zu ungewollten Konflikten kommt.<\/p>\n<h4 id=\"testen-bei-browserstack.com\">Testen bei Browserstack.com<\/h4>\n<p>Bei einer kleineren Testing-Suite ist es eher unwahrscheinlich, dass Browser und deren Versionen miteinander kollidieren. Aber bei einem sehr gro\u00dfen Grid, wie z.B. bei <a href=\"https:\/\/www.browserstack.com\/automate\">Browserstack<\/a>, welche ein fl\u00fcssige funktionierende Selenium-Umgebung bereitstellen, sollte man es sich angew\u00f6hnen seine <code>DesiredCapabilities<\/code> genau anzugeben, also mit Browser-Version und Betriebssystem.<\/p>\n<p>Bevor man Browserstack aber nutzen kann, muss man sein PHP-Script etwas anpassen:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$host<\/span> = <span class=\"st\">'http:\/\/hub.browserstack.com\/wd\/hub\/'<\/span><span class=\"ot\">;<\/span>\r\n<span class=\"kw\">$safari<\/span> = DesiredCapabilities::safari<span class=\"ot\">();<\/span>\r\n<span class=\"ot\">[<\/span><span class=\"st\">...<\/span><span class=\"ot\">]<\/span>\r\n<span class=\"kw\">$safari<\/span> -&gt; setCapability <span class=\"ot\">(<\/span> <span class=\"st\">'browserstack.user'<\/span><span class=\"ot\">,<\/span> <span class=\"st\">\"username\"<\/span> <span class=\"ot\">);<\/span>\r\n<span class=\"kw\">$safari<\/span> -&gt; setCapability <span class=\"ot\">(<\/span> <span class=\"st\">'browserstack.key'<\/span><span class=\"ot\">,<\/span> <span class=\"st\">\"userkey\"<\/span> <span class=\"ot\">);<\/span><\/code><\/pre>\n<p>So wei\u00df Browserstack n\u00e4mlich, unter welchem Account die Tests durchgef\u00fchrt werden.<\/p>\n<figure id=\"attachment_285\" aria-describedby=\"caption-attachment-285\" style=\"width: 300px\" class=\"wp-caption alignnone\"><img src=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-fertiges-selenium-grid-bei-browserstack-mit-unzaehligen-browsern-mehr-informationen-unter-browserstack.com-automate-https-www.browserstack.com-automate--300x230.png\" alt=\"Infografik #2: Fertiges Selenium Grid bei Browserstack mit unz\u00e4hligen Browsern\" width=\"300\" height=\"230\" class=\"size-medium wp-image-285\" srcset=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-fertiges-selenium-grid-bei-browserstack-mit-unzaehligen-browsern-mehr-informationen-unter-browserstack.com-automate-https-www.browserstack.com-automate--300x230.png 300w, https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-fertiges-selenium-grid-bei-browserstack-mit-unzaehligen-browsern-mehr-informationen-unter-browserstack.com-automate-https-www.browserstack.com-automate--768x590.png 768w, https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-fertiges-selenium-grid-bei-browserstack-mit-unzaehligen-browsern-mehr-informationen-unter-browserstack.com-automate-https-www.browserstack.com-automate--1024x786.png 1024w, https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-fertiges-selenium-grid-bei-browserstack-mit-unzaehligen-browsern-mehr-informationen-unter-browserstack.com-automate-https-www.browserstack.com-automate-.png 1051w, https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-fertiges-selenium-grid-bei-browserstack-mit-unzaehligen-browsern-mehr-informationen-unter-browserstack.com-automate-https-www.browserstack.com-automate--300x230@2x.png 600w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><figcaption id=\"caption-attachment-285\" class=\"wp-caption-text\">Infografik #2: Fertiges Selenium Grid bei Browserstack mit unz\u00e4hligen Browsern<\/figcaption><\/figure>\n<h4 id=\"opera-28-und-chrome-in-einem-grid\">Opera 28 und Chrome in einem Grid<\/h4>\n<p>Die <strong>Implementierung von Opera<\/strong> in das Selenium Grid ist seit Neuestem etwas tricky. Denn Opera basiert bereits seit einiger Zeit auf der <strong>Chrome-Engine Blink<\/strong> und verwendet somit <strong>seit der Version<\/strong> 26 nicht mehr den <strong>OperaPrestoDriver<\/strong>, sondern den <strong>OperaChromiumDriver<\/strong>.<\/p>\n<figure id=\"attachment_286\" aria-describedby=\"caption-attachment-286\" style=\"width: 300px\" class=\"wp-caption alignnone\"><img src=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-verschiedene-engine-versionen-von-opera-diagramm-auf-basis-von-offiziellen-opera-changelogs-http-www.opera_.com-docs-changelogs--300x153.png\" alt=\"Infografik #3: Verschiedene Engine-Versionen von Opera\" width=\"300\" height=\"153\" class=\"size-medium wp-image-286\" srcset=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-verschiedene-engine-versionen-von-opera-diagramm-auf-basis-von-offiziellen-opera-changelogs-http-www.opera_.com-docs-changelogs--300x153.png 300w, https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-verschiedene-engine-versionen-von-opera-diagramm-auf-basis-von-offiziellen-opera-changelogs-http-www.opera_.com-docs-changelogs-.png 588w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><figcaption id=\"caption-attachment-286\" class=\"wp-caption-text\">Infografik #3: Verschiedene Engine-Versionen von Opera<\/figcaption><\/figure>\n<p>Deswegen muss man auch bei der Implementierung ins Selenium Grid einiges beachten, damit man zwischen Chrome und Opera unterscheiden kann:<\/p>\n<h5 id=\"operachromiumdriver-starten-des-opera-nodes\">OperaChromiumDriver: Starten des Opera-Nodes<\/h5>\n<pre id=\"version\"><code>java -jar C:\/selenium\/selenium-server-standalone-2.44.0.jar \\\r\n  -role webdriver \\\r\n  -hub http:\/\/swuser-xubuntu:4444\/grid\/register \\\r\n  -browser browserName=*****chrome*****,maxInstances=4,platform=WINDOWS,version=*****opera28***** \\\r\n  -Dwebdriver.*****chrome*****.driver=C:\/selenium\/*****operachromedriver.exe***** \\\r\n  -port 5558\r\n# Man beachte die mit ***** hervorgehobenen Stellen<\/code><\/pre>\n<p>In der Versionsangabe steht also explizit <code>opera28<\/code>. Der Selenium Opera Node, der hier gestartet wird, ist also mit dieser Versionskennung eindeutig ausgewiesen.<\/p>\n<figure id=\"attachment_287\" aria-describedby=\"caption-attachment-287\" style=\"width: 300px\" class=\"wp-caption alignnone\"><img src=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-die-version-opera28-ist-auch-in-der-selenium-grid-console-sichtbar-300x191.png\" alt=\"Infografik #4: Die Version opera28 ist auch in der Selenium Grid Console sichtbar\" width=\"300\" height=\"191\" class=\"size-medium wp-image-287\" srcset=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-die-version-opera28-ist-auch-in-der-selenium-grid-console-sichtbar-300x191.png 300w, https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-die-version-opera28-ist-auch-in-der-selenium-grid-console-sichtbar.png 516w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><figcaption id=\"caption-attachment-287\" class=\"wp-caption-text\">Infografik #4: Die Version opera28 ist auch in der Selenium Grid Console sichtbar<\/figcaption><\/figure>\n<p>Die Parameter des Startbefehls eines <strong>Google Chrome Nodes<\/strong> sehen im Vergleich zum Opera Chromium Node wie folgt aus (Unterschiede sind fettgedruckt):<\/p>\n<table>\n<thead>\n<tr class=\"header\">\n<th align=\"left\">Parameter<\/th>\n<th align=\"left\">Chrome<\/th>\n<th align=\"left\">Opera Chromium<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"odd\">\n<td align=\"left\"><code>browserName<\/code><\/td>\n<td align=\"left\"><code>chrome<\/code><\/td>\n<td align=\"left\"><code>chrome<\/code><\/td>\n<\/tr>\n<tr class=\"even\">\n<td align=\"left\"><code>version<\/code><\/td>\n<td align=\"left\"><code>40.0<\/code><\/td>\n<td align=\"left\"><strong>opera28<\/strong><\/td>\n<\/tr>\n<tr class=\"odd\">\n<td align=\"left\">Web-Driver-Name<\/td>\n<td align=\"left\"><code>webdriver.chrome.driver<\/code><\/td>\n<td align=\"left\"><code>webdriver.chrome.driver<\/code><\/td>\n<\/tr>\n<tr class=\"even\">\n<td align=\"left\">Web-Driver-Pfad<\/td>\n<td align=\"left\"><code>C:\/selenium\/chromedriver.exe<\/code><\/td>\n<td align=\"left\"><strong>C:\/selenium\/operachromedriver.exe<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Die Unterschiede bestehen also in der Versionsangabe und im Pfad zur <strong>bin\u00e4ren Datei<\/strong> des WebDrivers.<\/p>\n<h5 id=\"operachromiumdriver-chrome-als-desiredcapabilities-angeben\">OperaChromiumDriver: <code>chrome<\/code> als DesiredCapabilities angeben<\/h5>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$opera<\/span> = DesiredCapabilities::chrome <span class=\"ot\">(<\/span> <span class=\"ot\">);<\/span><\/code><\/pre>\n<p>(Ja, obwohl es <em>Opera<\/em> werden soll, muss man hier <code>chrome<\/code> als <strong>DesiredCapabilities<\/strong> angeben)<\/p>\n<p>Um jetzt im PHP-Code zwischen einem Google Chrome Node und einem Opera Chromium Node unterscheiden zu k\u00f6nnen, spezifiziert man einfach die <a href=\"#version\">oben angegebene<\/a> Version:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n\r\n<span class=\"co\"># Google Chrome:<\/span>\r\n<span class=\"kw\">$chrome<\/span> = DesiredCapabilities::chrome <span class=\"ot\">(<\/span> <span class=\"ot\">);<\/span>\r\n<span class=\"kw\">$chrome<\/span>-&gt;setVersion<span class=\"ot\">(<\/span><span class=\"st\">'40.0'<\/span><span class=\"ot\">);<\/span>\r\n\r\n<span class=\"co\"># Opera Chromium:<\/span>\r\n<span class=\"kw\">$opera<\/span> = DesiredCapabilities::chrome <span class=\"ot\">(<\/span> <span class=\"ot\">);<\/span>\r\n<span class=\"kw\">$opera<\/span>-&gt;setVersion<span class=\"ot\">(<\/span><span class=\"st\">'opera28'<\/span><span class=\"ot\">);<\/span><\/code><\/pre>\n<h3 id=\"aufrufen-der-startseite\">Aufrufen der Startseite<\/h3>\n<p>Jetzt k\u00f6nnen wir einen <strong>RemoteWebdriver<\/strong> wie folgt verwenden, um die betreffende Seite aufzurufen:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$driver<\/span> = RemoteWebDriver::create <span class=\"ot\">(<\/span> <span class=\"kw\">$host<\/span><span class=\"ot\">,<\/span> <span class=\"kw\">$opera<\/span><span class=\"ot\">,<\/span> <span class=\"dv\">5000<\/span> <span class=\"ot\">);<\/span>\r\n<span class=\"kw\">$driver<\/span> -&gt; get<span class=\"ot\">(<\/span><span class=\"st\">\"http:\/\/www.budenheim.com\"<\/span><span class=\"ot\">);<\/span><\/code><\/pre>\n<h4 id=\"ansprechen-von-objekten\">Ansprechen von Objekten<\/h4>\n<p>Um in Selenium ein Objekt anzusprechen, gibt es einige M\u00f6glichkeiten zur Auswahl:<\/p>\n<ul>\n<li>\u00dcber die Klasse des Elements (<code>class<\/code>-HTML-Attribut)<\/li>\n<li>\u00dcber die ID des Elements (<code>id<\/code>-HTML-Attribut)<\/li>\n<li>\u00dcber den XPath des Elements<\/li>\n<\/ul>\n<p>Die \u00dcbersicht aller M\u00f6glichkeiten gibt die Autovervollst\u00e4ndigung in Eclipse:<\/p>\n<figure id=\"attachment_288\" aria-describedby=\"caption-attachment-288\" style=\"width: 300px\" class=\"wp-caption alignnone\"><img src=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-anhand-dieser-kriterien-kann-man-ein-element-mit-selenium-ansprechen-300x227.png\" alt=\"Infografik #5: Anhand dieser Kriterien kann man ein Element mit Selenium ansprechen\" width=\"300\" height=\"227\" class=\"size-medium wp-image-288\" srcset=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-anhand-dieser-kriterien-kann-man-ein-element-mit-selenium-ansprechen-300x227.png 300w, https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-anhand-dieser-kriterien-kann-man-ein-element-mit-selenium-ansprechen.png 407w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><figcaption id=\"caption-attachment-288\" class=\"wp-caption-text\">Infografik #5: Anhand dieser Kriterien kann man ein Element mit Selenium ansprechen<\/figcaption><\/figure>\n<p>In unserem Beispiel suchen wir Elemente anhand ihres XPath aus.<\/p>\n<h4 id=\"kleines-helferlein-firepath\">Kleines Helferlein: Firepath<\/h4>\n<p>Mit der FirePath-Extension von FireBug f\u00fcr Firefox kann man den XPath zu einem bestimmten Objekt schnell und einfach herauszufinden oder einen bereits vorhanden XPath auf Richtigkeit zu pr\u00fcfen:<\/p>\n<figure id=\"attachment_289\" aria-describedby=\"caption-attachment-289\" style=\"width: 300px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-firepath-hilft-beim-finden-eines-elements.png\"><img src=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-firepath-hilft-beim-finden-eines-elements-300x174.png\" alt=\"Infografik #6: FirePath hilft beim Finden eines Elements\" width=\"300\" height=\"174\" class=\"size-medium wp-image-289\" srcset=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-firepath-hilft-beim-finden-eines-elements-300x174.png 300w, https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/infografik-firepath-hilft-beim-finden-eines-elements.png 559w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-289\" class=\"wp-caption-text\">Infografik #6: FirePath hilft beim Finden eines Elements<\/figcaption><\/figure>\n<p>Den XPath kann man aus dem oberen Feld \u00fcbernehmen und in seinen <strong>Testplan<\/strong> implementieren.<\/p>\n<p>In den <strong>PHP-Bindings f\u00fcr Selenium<\/strong> spricht man ein Element mit der XPath-Methode wie folgt an:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$object<\/span> = <span class=\"kw\">$driver<\/span> -&gt; findElement <span class=\"ot\">(<\/span>\r\n  <span class=\"co\"># Das ist die f\u00fcr uns relevante Stelle:<\/span>\r\n  WebDriverBy::xpath<span class=\"ot\">(<\/span><span class=\"st\">\"\/\/*[contains(text(),'Deutsch')]\"<\/span><span class=\"ot\">)<\/span>\r\n<span class=\"ot\">);<\/span><\/code><\/pre>\n<p>Jetzt kann ich \u00fcber die Variable <code>$object<\/code> auf die Funktionen und Attribte des Elements, der den Text <code>Deutsch<\/code> enth\u00e4lt, zugreifen und ggf. ver\u00e4ndern.<\/p>\n<h3 id=\"ladezeiten-\u00fcberbr\u00fccken\">Ladezeiten \u00fcberbr\u00fccken<\/h3>\n<p>Das ist ja sch\u00f6n, dass wir unsere Seite <em>aufgerufen<\/em> haben. Aber wie \u00fcberbr\u00fcckt man jetzt die Ladezeit? Was ist, wenn in der Seite <strong>Elemente dynamisch nachgeladen<\/strong> werden (AJAX)?<\/p>\n<h4 id=\"php-sleep-methode\">PHP-sleep()-Methode<\/h4>\n<p>Man kann entweder die Holzhammermethode anwenden und im PHP-Script einfach ein <code>sleep(10)<\/code> einbauen. Der Nachteil dieser Methode ist aber, dass das Testing so sehr viel unn\u00f6tige Wartezeit beinhaltet. Das ist nicht mehr <strong>optimtiert<\/strong> und auch einfach nicht sauber programmiert.<\/p>\n<h4 id=\"warten-auf-existenz-eines-objekts\">Warten auf Existenz eines Objekts<\/h4>\n<p>Viel besser ist es hier, <strong>auf ein bestimmtes Objekt zu warten<\/strong>, bis es vorhanden ist. Dabei sprechen wir das Objekt \u00fcber XPath an:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$driver<\/span> -&gt;\r\n  wait <span class=\"ot\">(<\/span> <span class=\"dv\">10<\/span> <span class=\"ot\">)<\/span> -&gt;\r\n  until <span class=\"ot\">(<\/span>\r\n    WebDriverExpectedCondition::presenceOfAllElementsLocatedBy <span class=\"ot\">(<\/span>\r\n      WebDriverBy::xpath<span class=\"ot\">(<\/span><span class=\"st\">\"\/\/*[contains(text(),'Deutsch')]\"<\/span><span class=\"ot\">)<\/span>\r\n    <span class=\"ot\">)<\/span>\r\n  <span class=\"ot\">);<\/span><\/code><\/pre>\n<p>Selenium wartet hier maximal <code>10<\/code> Sekunden, bis das Objekt existiert. Wenn nicht, wirft es eine Exception.<\/p>\n<h3 id=\"auf-ausf\u00fchrung-von-ajax-warten\">Auf Ausf\u00fchrung von AJAX warten<\/h3>\n<p>Das gleiche Prinzip wenden wir an, wenn wir auf die Ausf\u00fchrung von AJAX warten: Wir triggern eine asynchrone Ausf\u00fchrung von einem Script, z.B. indem wir einen Link anklicken &#8230;<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$object<\/span>-&gt;click<span class=\"ot\">();<\/span><\/code><\/pre>\n<p>&#8230; und wieder auf ein Element warten:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$driver<\/span> -&gt;\r\n  wait <span class=\"ot\">(<\/span> <span class=\"dv\">10<\/span> <span class=\"ot\">)<\/span> -&gt;\r\n  until <span class=\"ot\">(<\/span>\r\n    WebDriverExpectedCondition::presenceOfAllElementsLocatedBy <span class=\"ot\">(<\/span>\r\n      WebDriverBy::xpath<span class=\"ot\">(<\/span><span class=\"st\">\"***** XPath des zu erwartenden Elements hier eintragen*****\"<\/span><span class=\"ot\">)<\/span>\r\n    <span class=\"ot\">)<\/span>\r\n  <span class=\"ot\">);<\/span><\/code><\/pre>\n<h3 id=\"pr\u00fcfen-des-inhalts-eines-elements\">Pr\u00fcfen des Inhalts eines Elements<\/h3>\n<p>Da wir unser Objekt bereits in der Variable <code>$object<\/code> referenziert haben, kann man auch ganz leicht auf dessen Eigenschaften (und logischerweise auch den Text) zugreifen:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$objectText<\/span> = <span class=\"kw\">$object<\/span> -&gt; <span class=\"fu\">getText<\/span><span class=\"ot\">();<\/span><\/code><\/pre>\n<p>Diesen Text kann man dann je nach <strong>Testimplementierung<\/strong> pr\u00fcfen und dementsprechen reagieren.<\/p>\n<h3 id=\"screenshot-erstellen\">Screenshot erstellen<\/h3>\n<p>Wenn z.B. der Inhalt eines Elements nicht korrekt ist, kann man von der Seite einen Screenshot erstellen:<\/p>\n<pre class=\"sourceCode php\"><code class=\"sourceCode php\"><span class=\"kw\">&lt;?php<\/span>\r\n<span class=\"kw\">$driver<\/span> -&gt; takeScreenshot <span class=\"ot\">(<\/span> <span class=\"st\">'\/tmp\/screenshot.png'<\/span> <span class=\"ot\">);<\/span><\/code><\/pre>\n<p>Die Bildschirmaufnahme kann man dann entweder weiter bearbeiten (zuschneiden, bestimmte Elemente hervorheben, etc.) oder in seine Reports integrieren.<\/p>\n<h2 id=\"schlusswort-automated-website-testing-lohnt-sich\">Selenium Tutorial: Automated Website-Testing lohnt sich<\/h2>\n<p>Mit Selenium kann man also nach etwas Einrichtungszeit <strong>effektive und zeitsparende Website-Tests<\/strong> implementieren. Um mehr Funktionsumfang zu erreichen, ist es m\u00f6glich Linux-Tools \u00fcber PHP anzukoppeln und weitere PHP-Bibliotheken, zum Beispiel zur Reportgenerierung, einzubinden. Da die <strong>PHP-Selenium-API<\/strong> objektorientiert ist, hat man eine gro\u00dfe Bandbreite an M\u00f6glichkeiten, die bei entsprechender Implementierung nicht nur sehr gut wartbare Testanweisungen erm\u00f6glichen, sondern auch der Qualit\u00e4t der &#8222;in die Mangel genommenen&#8220; Website zugutekommen.<\/p>\n<p>Infografiken: \u00a9 schwarzer.de, Titelbild: I, <a href=\"http:\/\/commons.wikimedia.org\/wiki\/User:Lviatour\" title=\"User:Lviatour\">Luc Viatour<\/a> [<a href=\"http:\/\/www.gnu.org\/copyleft\/fdl.html\">GFDL<\/a>, <a href=\"http:\/\/creativecommons.org\/licenses\/by-sa\/3.0\/\">CC-BY-SA-3.0<\/a> or <a href=\"http:\/\/creativecommons.org\/licenses\/by-sa\/2.5-2.0-1.0\">CC BY-SA 2.5-2.0-1.0<\/a>], <a href=\"http:\/\/commons.wikimedia.org\/wiki\/File%3ADew_on_spider_web_Luc_Viatour.jpg\">via Wikimedia Commons<\/a><!-- <\/ezTOC> --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nachdem wir die Architektur von Selenium Grid verstanden und unseren ersten Selenium Hub und Node gestartet haben ist es nun [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":298,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[52,286],"tags":[295,297,299,302,303,304,305,307,308,309,310,311,312],"features_image":"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/Dew_on_spider_web_Luc_Viatour.altered.jpg","rk_cat":null,"rk_date":"19.03.2015","yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v18.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Selenium Tutorial deutsch: Testen von dynamischen Webapplikationen mit PHP und Selenium Grid - Schwarzer.de Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Selenium Tutorial deutsch: Testen von dynamischen Webapplikationen mit PHP und Selenium Grid - Schwarzer.de Blog\" \/>\n<meta property=\"og:description\" content=\"Nachdem wir die Architektur von Selenium Grid verstanden und unseren ersten Selenium Hub und Node gestartet haben ist es nun [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/\" \/>\n<meta property=\"og:site_name\" content=\"Schwarzer.de Blog\" \/>\n<meta property=\"article:published_time\" content=\"2015-03-19T10:36:34+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-09-17T13:41:29+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/Dew_on_spider_web_Luc_Viatour.altered.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1620\" \/>\n\t<meta property=\"og:image:height\" content=\"666\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Geschrieben von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Hans-J\u00fcrgen Schwarzer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/schwarzer.de\/blog\/#website\",\"url\":\"https:\/\/schwarzer.de\/blog\/\",\"name\":\"Schwarzer.de Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/schwarzer.de\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"de-DE\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/#primaryimage\",\"inLanguage\":\"de-DE\",\"url\":\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/Dew_on_spider_web_Luc_Viatour.altered.jpg\",\"contentUrl\":\"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/Dew_on_spider_web_Luc_Viatour.altered.jpg\",\"width\":1620,\"height\":666,\"caption\":\"I, Luc Viatour [GFDL (http:\/\/www.gnu.org\/copyleft\/fdl.html), CC-BY-SA-3.0 (http:\/\/creativecommons.org\/licenses\/by-sa\/3.0\/) or CC BY-SA 2.5-2.0-1.0 (http:\/\/creativecommons.org\/licenses\/by-sa\/2.5-2.0-1.0)], via Wikimedia Commons\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/#webpage\",\"url\":\"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/\",\"name\":\"Selenium Tutorial deutsch: Testen von dynamischen Webapplikationen mit PHP und Selenium Grid - Schwarzer.de Blog\",\"isPartOf\":{\"@id\":\"https:\/\/schwarzer.de\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/#primaryimage\"},\"datePublished\":\"2015-03-19T10:36:34+00:00\",\"dateModified\":\"2020-09-17T13:41:29+00:00\",\"author\":{\"@id\":\"https:\/\/schwarzer.de\/blog\/#\/schema\/person\/b4ffeb0c116fc217c80baefd49bc381a\"},\"breadcrumb\":{\"@id\":\"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/#breadcrumb\"},\"inLanguage\":\"de-DE\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\/\/schwarzer.de\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Selenium Tutorial deutsch: Testen von dynamischen Webapplikationen mit PHP und Selenium Grid\"}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/schwarzer.de\/blog\/#\/schema\/person\/b4ffeb0c116fc217c80baefd49bc381a\",\"name\":\"Hans-J\u00fcrgen Schwarzer\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/schwarzer.de\/blog\/#personlogo\",\"inLanguage\":\"de-DE\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/64690c1ea3ab46fac7afd4778bc78364?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/64690c1ea3ab46fac7afd4778bc78364?s=96&d=mm&r=g\",\"caption\":\"Hans-J\u00fcrgen Schwarzer\"},\"description\":\"Hans-J\u00fcrgen Schwarzer leitet die Digital-Agentur schwarzer.de software + internet gmbh. Als Unternehmer und Verleger in Personalunion wie auch als leidenschaftlicher Blogger geh\u00f6rt er zu den Hauptautoren verschiedener Online-Magazine. Innerhalb seiner breiten Palette an Themen liegen dem Mainzer Lokalpatrioten dabei vermeintlich \u201eschr\u00e4ge\u201c Ideen und technische Novit\u00e4ten besonders am Herzen - Nerdstuff, wie es heute hei\u00dft.\",\"url\":\"#\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Selenium Tutorial deutsch: Testen von dynamischen Webapplikationen mit PHP und Selenium Grid - Schwarzer.de Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/","og_locale":"de_DE","og_type":"article","og_title":"Selenium Tutorial deutsch: Testen von dynamischen Webapplikationen mit PHP und Selenium Grid - Schwarzer.de Blog","og_description":"Nachdem wir die Architektur von Selenium Grid verstanden und unseren ersten Selenium Hub und Node gestartet haben ist es nun [&hellip;]","og_url":"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/","og_site_name":"Schwarzer.de Blog","article_published_time":"2015-03-19T10:36:34+00:00","article_modified_time":"2020-09-17T13:41:29+00:00","og_image":[{"width":1620,"height":666,"url":"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/Dew_on_spider_web_Luc_Viatour.altered.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Geschrieben von":"Hans-J\u00fcrgen Schwarzer","Gesch\u00e4tzte Lesezeit":"8 Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebSite","@id":"https:\/\/schwarzer.de\/blog\/#website","url":"https:\/\/schwarzer.de\/blog\/","name":"Schwarzer.de Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/schwarzer.de\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"de-DE"},{"@type":"ImageObject","@id":"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/#primaryimage","inLanguage":"de-DE","url":"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/Dew_on_spider_web_Luc_Viatour.altered.jpg","contentUrl":"https:\/\/schwarzer.de\/blog\/wp-content\/uploads\/2015\/03\/Dew_on_spider_web_Luc_Viatour.altered.jpg","width":1620,"height":666,"caption":"I, Luc Viatour [GFDL (http:\/\/www.gnu.org\/copyleft\/fdl.html), CC-BY-SA-3.0 (http:\/\/creativecommons.org\/licenses\/by-sa\/3.0\/) or CC BY-SA 2.5-2.0-1.0 (http:\/\/creativecommons.org\/licenses\/by-sa\/2.5-2.0-1.0)], via Wikimedia Commons"},{"@type":"WebPage","@id":"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/#webpage","url":"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/","name":"Selenium Tutorial deutsch: Testen von dynamischen Webapplikationen mit PHP und Selenium Grid - Schwarzer.de Blog","isPartOf":{"@id":"https:\/\/schwarzer.de\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/#primaryimage"},"datePublished":"2015-03-19T10:36:34+00:00","dateModified":"2020-09-17T13:41:29+00:00","author":{"@id":"https:\/\/schwarzer.de\/blog\/#\/schema\/person\/b4ffeb0c116fc217c80baefd49bc381a"},"breadcrumb":{"@id":"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/#breadcrumb"},"inLanguage":"de-DE","potentialAction":[{"@type":"ReadAction","target":["https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/schwarzer.de\/blog\/tutorial-testen-von-dynamischen-webapplikationen-mit-php-und-selenium-grid\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/schwarzer.de\/blog\/"},{"@type":"ListItem","position":2,"name":"Selenium Tutorial deutsch: Testen von dynamischen Webapplikationen mit PHP und Selenium Grid"}]},{"@type":"Person","@id":"https:\/\/schwarzer.de\/blog\/#\/schema\/person\/b4ffeb0c116fc217c80baefd49bc381a","name":"Hans-J\u00fcrgen Schwarzer","image":{"@type":"ImageObject","@id":"https:\/\/schwarzer.de\/blog\/#personlogo","inLanguage":"de-DE","url":"https:\/\/secure.gravatar.com\/avatar\/64690c1ea3ab46fac7afd4778bc78364?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/64690c1ea3ab46fac7afd4778bc78364?s=96&d=mm&r=g","caption":"Hans-J\u00fcrgen Schwarzer"},"description":"Hans-J\u00fcrgen Schwarzer leitet die Digital-Agentur schwarzer.de software + internet gmbh. Als Unternehmer und Verleger in Personalunion wie auch als leidenschaftlicher Blogger geh\u00f6rt er zu den Hauptautoren verschiedener Online-Magazine. Innerhalb seiner breiten Palette an Themen liegen dem Mainzer Lokalpatrioten dabei vermeintlich \u201eschr\u00e4ge\u201c Ideen und technische Novit\u00e4ten besonders am Herzen - Nerdstuff, wie es heute hei\u00dft.","url":"#"}]}},"_links":{"self":[{"href":"https:\/\/schwarzer.de\/blog\/wp-json\/wp\/v2\/posts\/282"}],"collection":[{"href":"https:\/\/schwarzer.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/schwarzer.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/schwarzer.de\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/schwarzer.de\/blog\/wp-json\/wp\/v2\/comments?post=282"}],"version-history":[{"count":19,"href":"https:\/\/schwarzer.de\/blog\/wp-json\/wp\/v2\/posts\/282\/revisions"}],"predecessor-version":[{"id":1307,"href":"https:\/\/schwarzer.de\/blog\/wp-json\/wp\/v2\/posts\/282\/revisions\/1307"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/schwarzer.de\/blog\/wp-json\/wp\/v2\/media\/298"}],"wp:attachment":[{"href":"https:\/\/schwarzer.de\/blog\/wp-json\/wp\/v2\/media?parent=282"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/schwarzer.de\/blog\/wp-json\/wp\/v2\/categories?post=282"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/schwarzer.de\/blog\/wp-json\/wp\/v2\/tags?post=282"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}