{"id":1145,"date":"2017-04-06T13:21:29","date_gmt":"2017-04-06T13:21:29","guid":{"rendered":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/?p=1145"},"modified":"2020-07-22T14:15:27","modified_gmt":"2020-07-22T14:15:27","slug":"protractor-automatisiert-testen-mit-angular","status":"publish","type":"post","link":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/","title":{"rendered":"Protractor \u2013 Automatisiert Testen mit Angular"},"content":{"rendered":"\n<p>Kritische Fehler, die erst im Rahmen des Live-Betriebes \u00f6ffentlich werden, stellen ein gro\u00dfes finanzielles Risiko und nicht zuletzt eine negative Werbung f\u00fcr ein Produkt und die beteiligten Unternehmen dar. Deshalb ist das Thema Test in der modernen Softwareentwicklung ein grundlegender und integraler Bestandteil. Durch eine hohe Testabdeckung und der zeitnahen R\u00fcckmeldung der Testergebnisse l\u00e4sst sich die Qualit\u00e4t und Reife des Produktes ausreichend genau nachweisen und best\u00e4tigen.<\/p>\n\n\n\n<p>Eine L\u00f6sung, die eine schnelle Durchf\u00fchrung dieser Tests erm\u00f6glicht und den Anforderungen moderner Entwicklungsprojekte entspricht, ist der Einsatz von Testautomatisierungswerkzeugen. Diese Werkzeuge arbeiten nach dem Prinzip der toolgesteuerten Aufnahme von Informationen \u00fcber die grafische Oberfl\u00e4che des Testobjekts und der damit m\u00f6glichen automatisierten Durchf\u00fchrung von skriptgebundenen Interaktionen sowie der daraus resultierenden Pr\u00fcfung der jeweiligen Applikation.<\/p>\n\n\n\n<p>Testautomatisierungswerkzeuge sorgen f\u00fcr eine schnelle und kontinuierliche R\u00fcckmeldung \u00fcber den Stand der Qualit\u00e4t der zu testenden Software. Aber bei ihrem Einsatz m\u00fcssen einige Punkte beachtet werden. Es gibt verschiedene Werkzeuge auf dem Markt die unterschiedliche Ans\u00e4tze w\u00e4hlen, wie sie sich in den Entwicklungs- und Testprozess integrieren oder welche Technologien sie unterst\u00fctzen. Der effektive Einsatz einer Testautomatisierungsl\u00f6sung steht und f\u00e4llt mit der verwendeten Engine, die zur Ansteuerung der grafischen Oberfl\u00e4che genutzt wird. Diese muss die zu testende Technologie optimal unterst\u00fctzen. Besonders Entwicklungsprojekte, die \u201cneue\u201d Technologien wie Angular2 einsetzen, haben die Herausforderung, dass die vorhandenen und bekannten Werkzeuge nicht immer auf dem gleichen Stand sind wie ihr Arbeitsgegenstand.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Projekt CLINTR und Tests mit Protractor<\/h2>\n\n\n\n<p>In unserem aktuellen Softwareentwicklungsprojekt Clintr nutzen wir Angular2 als Entwicklungsframework und wollten von Beginn an eine hohe Dichte von automatisierten Testf\u00e4llen. Clintr ist eine Web-Anwendung, die Dienstleister auf potenzielle Kunden in ihrem Kontaktnetzwerk aufmerksam macht. Dazu werden Daten der angebotenen XING-API verwendet und analysiert, um nach bestimmten Kriterien vollautomatisiert einen Dienstleistungsbedarf bei Firmen abzuleiten. Wurde ein Dienstleistungsbedarf einer Firma identifiziert, sucht Clintr im Kontaktnetzwerk (z.B. XING oder CRM-Systeme) des Dienstleisters nach Kontaktpfaden zum potenziellen Kunden. Im Backend kommen Spring Boot basierte Microservices mit Kubernetes als Container Cluster Manager zum Einsatz, w\u00e4hrend im Frontend Angular (&gt;2) eingesetzt wird. Um hochfrequent neue Versionen der Anwendung ver\u00f6ffentlichen zu k\u00f6nnen, wurde eine Continuous Delivery Pipeline in die Google-Cloud etabliert und das f\u00fcr Test- bzw. Produktionsumgebung.<\/p>\n\n\n\n<p>Wir haben uns durch den Einsatz von Angular2 f\u00fcr das Automatisierungs-Testwerkzeug Protractor entschieden. Protractor baut auf Selenium und dem WebDriver Framework auf. Wie gewohnt laufen die Oberfl\u00e4chentests im Browser ab und simulieren das Verhalten eines Nutzers, der die Anwendung verwendet. Da Protractor direkt f\u00fcr Angular geschrieben wurde, kann es auf alle Angular-Elemente ohne Einschr\u00e4nkungen zugreifen. Dar\u00fcber hinaus werden keine zus\u00e4tzlichen Anweisungen f\u00fcr das Warten auf Komponenten wie \u201csleeps\u201c oder \u201cwaits\u201c ben\u00f6tigt, da Protractor selbst erkennt, in welchem Status die Komponenten sich befinden bzw. ob sie f\u00fcr die anstehende Interaktion zur Verf\u00fcgung stehen.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">How To<\/h2>\n\n\n\n<p>F\u00fcr die Inbetriebnahme ben\u00f6tigt man AngularCLI und NodeJS. Danach k\u00f6nnen im Projekt die Oberfl\u00e4chentests (end-to-end oder <em>e2e<\/em>) erstellt werden. Zur Vorbereitung der lokalen Testausf\u00fchrung wechselt man mit der Konsole in das Projekt-Verzeichnis und gibt \u201cng serve\u201d ein. Nach der Eingabe von \u201cng e2e\u201d werden die Testf\u00e4lle dann auf dem <em>localhost<\/em> ausgef\u00fchrt.<\/p>\n\n\n\n<p>Die end-to-end Tests bestehen aus Type Script Dateien mit der Endung <em>.e2e-spec.ts<\/em>, <em>.po.ts<\/em> oder nur <em>.ts<\/em>. In den Dateien, die mit <em>.e2e-spec.ts<\/em> enden, werden die Testf\u00e4lle beschrieben. Nur Tests die in diesen Dateien stehen werden ausgef\u00fchrt. In dem folgenden Beispiel sieht man den Kopf einer <em>.e2e-spec.ts-Datei<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    import { browser, by, ElementFinder } from 'protractor';\n    import { ResultPage } from '.\/result-list.po';\n    import { CommonTabActions } from '.\/common-tab-actions';\n    import { SearchPage } from '.\/search.po';\n    import { AppPage } from '.\/app.po';\n    import { CardPageObject } from '.\/card.po';\n    import * as webdriver from 'selenium-webdriver';\n    import ModulePromise = webdriver.promise;\n    import Promise = webdriver.promise.Promise;\n     \n    describe('Result list', function () {\n     \n     let app: AppPage;\n     let result: ResultPage;\n     let common: CommonTabActions;\n     let search: SearchPage;\n     \n     beforeEach(() => {\n     app = new AppPage();\n     result = new ResultPage();\n     common = new CommonTabActions();\n     search = new SearchPage();\n     result.navigateTo();\n     });<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Diese wird wie auch die anderen Dateitypen mit den Importen er\u00f6ffnet. Darauf folgt der Beginn der Testf\u00e4lle mit <em>describe<\/em>. In dem String in der Klammer wird angeben, welcher Bereich getestet werden soll. Darunter werden die einzelnen <em>.po.ts<\/em> Dateien angelegt und instanziiert, die f\u00fcr die darauffolgenden Tests ben\u00f6tigt werden. Durch die <em>beforeEach<\/em> Anweisung lassen sich Vorbedingungen f\u00fcr den Test definieren. Zum Zweck der Wiederverwendbarkeit lassen sich die Tests auch in Module auslagern (siehe nachfolgendes Code-Beispiel):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    it('should display the correct background-image when accessing the page', require('.\/background'));\n    it('should send me to the impressum page', require('.\/impressum'));\n    it('should send me to the privacy-policy page', require('.\/privacy-policy'));\n     \n    it('should open the search page after clicking clintr logo', require('.\/logo'));<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Im nachfolgenden Code sind normale e2e Tests aufgef\u00fchrt. Dort steht zuerst, was erwartet wird und danach die Ausf\u00fchrung des Tests. Hierbei sollte man sich merken, dass die e2e Tests in der <em>.e2e-spec.ts<\/em> nur die Methoden der <em>.po.ts<\/em> aufruft, und dann das Ergebnis zur\u00fcckerwartet. Die ausf\u00fchrenden Methoden geh\u00f6ren in die <em>.po.ts<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    it('should still show the elements of the searchbar', () => {\n     expect(result.isSearchFieldDisplayed()).toBe(true);\n     expect(result.isSearchButtonDisplayed()).toBe(true);\n    });\n     \n    it('should show the correct Search Term', () => {\n     expect(result.getSearchTerm()).toBe(result.searchTerm);\n    });<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Das nachfolgende Code-Beispiel zeigt die zu der vorherigen <em>.e2e-spec.ts<\/em> geh\u00f6rigen <em>.po.ts<\/em>. Es ist nicht zwingend notwendig, dass jede <em>.e2e-spec.ts<\/em> ihre eigene <em>.po.ts<\/em> hat oder umgekehrt. Zum Beispiel kann eine <em>.po.ts<\/em> Aktionen von Tabs enthalten, wie Tab wechseln oder schlie\u00dfen. Solange eine <em>.e2e-spec.ts<\/em> nur Methoden von anderen <em>.po.ts<\/em> benutzt, ben\u00f6tigt sie nicht zwingend eine eigene <em>.po.ts<\/em>. Wie vorher erw\u00e4hnt, beginnt die <em>.po.ts<\/em> mit den Importen und danach wird Klasse (im Beispiel <em>ResultPage<\/em>) erstellt.<\/p>\n\n\n\n<p>Die <em>navigateTo<\/em> Methode l\u00e4sst den Test bei ihrem Aufruf auf die vorgesehene Seite springen. Da der Test das in diesem Fall nicht direkt machen soll, geht er zuerst auf die S<em>earch<\/em> Seite. Dort wird ein Suchbegriff eingegeben und die Suche gestartet. Somit kommt der Test auf die <em>result_list<\/em> Seite, wo dann die Tests ausgef\u00fchrt werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    import { element, by, ElementFinder, browser } from 'protractor';\n    import { SearchPage } from '.\/search.po';\n    import * as webdriver from 'selenium-webdriver';\n    import { CardPageObject } from '.\/card.po';\n    import ModulePromise = webdriver.promise;\n    import Promise = webdriver.promise.Promise;\n     \n    export class ResultPage {\n     \n     public searchTerm: string = 'test';\n     \n     search: SearchPage;\n     \n     navigateTo(): Promise&lt;void> {\n     this.search = new SearchPage();\n     return this.search.navigateTo()\n     .then(() => this.search.setTextInSearchField(this.searchTerm))\n     .then(() => this.search.clickSearchButton());\n     }<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>In den drei nachfolgenden Methoden wird jeweils ein Element der Seite abgefragt. Die ersten zwei Tests haben als R\u00fcckgabewert einen <em>Union Type<\/em>. Das hei\u00dft, dass entweder ein <em>boolean<\/em> oder ein <em>Promise&lt;boolean&gt;<\/em> zur\u00fcckgegeben werden kann. Also entweder ein <em>Boolean<\/em> oder das Versprechen auf einen <em>Boolean<\/em>. Wenn man mit dem R\u00fcckgabewert <em>Promise<\/em> arbeitet, sollte darauf immer ein <em>then<\/em> folgen, da es sonst zu asynchronen Fehlern kommen kann.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    isSearchButtonDisplayed(): Promise&lt;boolean> | boolean {\n     return element(by.name('searchInputField')).isDisplayed();\n    }\n     \n    isSearchFieldDisplayed(): Promise&lt;boolean> | boolean {\n     return element(by.name('searchButton')).isDisplayed();\n    }\n     \n    getSearchTerm(): Promise&lt;string> {\n     return element(by.name('searchInputField')).getAttribute('value');\n    }<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Beispiel<\/h2>\n\n\n\n<p>Ein Umsetzungsbeispiel f\u00fcr einen Testfall in ClintR ist der Test des Impressumlinks. Er soll zuerst den Link dr\u00fccken. Danach soll der Test auf den neu entstandenen Tab wechseln und best\u00e4tigen, ob die URL <em>\/legal-notice<\/em> enth\u00e4lt. Als letztes soll er diesen Tab wieder schlie\u00dfen. Dieser Test wurde erst nur f\u00fcr die Startseite erstellt.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    it('should send me to the impressum page',() => {\n     impressum.clickImpressumLink();\n     common.switchToAnotherTab(1);\n     expect(browser.getCurrentUrl()).toContain('\/legal-notice');\n     common.closeSelectedTab(1);\n    })<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Da das Impressum, laut Akzeptanzkriterium, von allen Unterseiten erreichbar sein muss, wurde dieser sp\u00e4ter in alle anderen Specs \u00fcbertragen. Um den Code \u00fcbersichtlich zu halten, wurde entschieden, diesen Test in ein Modul (<em>impressum.ts<\/em>) auszulagern.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    import { browser } from 'protractor';\n    import { AppPage } from '.\/app.po';\n    import { CommonTabActions } from '.\/common-tab-actions';\n     \n    module.exports = () => {\n     let common: CommonTabActions = new CommonTabActions();\n     new AppPage().clickImpressumLink().then(() => {\n     common.switchToAnotherTab(1);\n     expect(browser.getCurrentUrl()).toContain('\/legal-notice');\n     common.closeSelectedTab(1);\n     });\n    };<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Die Verwendung in der&nbsp;<em>e2e-spec.ts<\/em> erfolgt auf diesem Wege:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    it('should send me to the impressum page', require('.\/impressum'));<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Besonderheiten, Hinweise &amp; Probleme<\/h2>\n\n\n\n<p>In jeder <em>e2e-spec.ts<\/em> k\u00f6nnen bestimmte vorgegebene Anweisungen geschrieben werden \u2013 z.B. <strong><em>beforeEach<\/em><\/strong>, <strong><em>beforeAll<\/em> <\/strong>oder <strong><em>afterEach<\/em> <\/strong>und <strong><em>afterAll<\/em><\/strong>. Wie die Namen schon sagen, wird der Code, der in einer dieser Anweisung steht, vor bzw. nach jedem oder allen Tests ausgef\u00fchrt. In unserem Beispiel sollte jeder Test seinen eigenen Seitenaufruf haben. Somit kann z.B. die <em>navigateTo<\/em> Methode in die <em>beforeEach<\/em> Anweisung geschrieben werden. <em>afterEach<\/em> kann z.B. daf\u00fcr genutzt werden, Tabs, die w\u00e4hrend der Tests ge\u00f6ffnet worden sind, wieder zu schlie\u00dfen.<\/p>\n\n\n\n<p>Jeder Test beginnt mit dem Wort <strong><em>it<\/em><\/strong>. Wenn man vor diesem Wort ein x schreibt, also <strong><em>xit<\/em><\/strong>, wird dieser Test bei der Testausf\u00fchrung \u00fcbersprungen. Es wird dann aber bei der Testausf\u00fchrung anders als bei einem auskommentierten Test mitgeteilt, dass ein oder mehrere Tests \u00fcbersprungen worden sind. Sollte man einen Testfall mit f schreiben, also <strong><em>fit<\/em><\/strong>, werden nur noch Tests bei der Ausf\u00fchrung ber\u00fccksichtigt, die auch ein <em>fit<\/em> davor stehen haben. Das ist n\u00fctzlich, wenn man sehr viele Testf\u00e4lle hat und man nur einige von ihnen laufen lassen will.<\/p>\n\n\n\n<p>Beim Arbeiten mit <em>Promise<\/em>, die man aus manchen Methoden erh\u00e4lt, sollte man darauf achten, dass es bei falscher Handhabung zu <strong>asynchronen Fehlern<\/strong> kommen kann. Viele Ereignisse wie das Dr\u00fccken eines Buttons oder die Abfrage, ob ein Element angezeigt wird, erzeugen als Wiedergabewert ein solches <em>Promise<\/em>. Selbst das \u00d6ffnen einer Seite gibt ein <em>Promise&lt;void&gt;<\/em> zur\u00fcck. Um Fehler zu vermeiden sollte auf jedes <em>Promise<\/em>, welches weitere Aktionen nach sich zieht, wie das Dr\u00fccken eines Buttons und die Ausgabe von einem dadurch entstandenen Wert, explizit mit <em>then<\/em> reagiert werden. Zum Beispiel:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    dr\u00fcckeButton().then( () => {\n     gibMirDenEntstandenenWert();\n    });\n    \/\/Wenn dieser Wert wieder ein Promise ist, der etwas ausl\u00f6sen soll, dann w\u00fcrde das Ganze so aussehen:\n    dr\u00fcckeButton().then( () => {\n     gibMirDenEntstandenenWert().then( () => {\n     machNochEtwas();\n     });\n    });\n    \/\/ oder etwas k\u00fcrzer\n    dr\u00fcckeButton()\n     .then(gibMirDenEntstandenenWert)\n     .then(machNochEtwas);<\/code><\/pre>\n\n\n\n<div style=\"height:40px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>F\u00fcr weitere Informationen zum Thema <em>Promise<\/em> siehe <a href=\"https:\/\/spin.atomicobject.com\/2014\/12\/17\/asynchronous-testing-protractor-angular\/\" target=\"_blank\" rel=\"noreferrer noopener\">hier<\/a>.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Fazit<\/h3>\n\n\n\n<p>Protractor eignet sich sehr gut f\u00fcr die Automatisierung von Oberfl\u00e4chentests in einem Softwareentwicklungsprojekt mit Angular2. Die Dokumentation seitens des Projektes ist sehr ausf\u00fchrlich und umfangreich. Durch die Nutzung von Selenium lassen sich die Tests ohne Probleme in den Buildprozess einbinden.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Kritische Fehler, die erst im Rahmen des Live-Betriebes \u00f6ffentlich werden, stellen ein gro\u00dfes finanzielles Risiko und nicht zuletzt eine negative Werbung f\u00fcr ein Produkt und die beteiligten Unternehmen dar. Deshalb ist das Thema Test in der modernen Softwareentwicklung ein grundlegender und integraler Bestandteil.<\/p>\n","protected":false},"author":39,"featured_media":1176,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"advgb_blocks_editor_width":"","advgb_blocks_columns_visual_guide":"","footnotes":""},"categories":[10,11],"tags":[23,30,41,52,463],"topics":[227],"class_list":["post-1145","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-qualitaetssicherung","category-web","tag-quality-assurance","tag-qualitaetssicherung","tag-automatisiertes-testen","tag-testautomatisierung","tag-protractor","topics-testautomatisierung"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Protractor - Automatisiert Testen mit Angular- ZEISS Digital Innovation Blog<\/title>\n<meta name=\"description\" content=\"Das Thema Test ist heute in der Softwareentwicklung ein grundlegender Bestandteil, um zu vermeiden, dass kritische Fehler erst beim Live-Betrieb auftauchen.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Protractor - Automatisiert Testen mit Angular- ZEISS Digital Innovation Blog\" \/>\n<meta property=\"og:description\" content=\"Das Thema Test ist heute in der Softwareentwicklung ein grundlegender Bestandteil, um zu vermeiden, dass kritische Fehler erst beim Live-Betrieb auftauchen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/\" \/>\n<meta property=\"og:site_name\" content=\"Digital Innovation Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/ZEISSDigitalInnovation\/\" \/>\n<meta property=\"article:published_time\" content=\"2017-04-06T13:21:29+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-07-22T14:15:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2017\/04\/201704_protractor_fi.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1281\" \/>\n\t<meta property=\"og:image:height\" content=\"734\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Niels Brestrich\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ZEISS_di\" \/>\n<meta name=\"twitter:site\" content=\"@ZEISS_di\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Niels Brestrich\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"9\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/\",\"name\":\"Protractor - Automatisiert Testen mit Angular- ZEISS Digital Innovation Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2017\/04\/201704_protractor_fi.png\",\"datePublished\":\"2017-04-06T13:21:29+00:00\",\"dateModified\":\"2020-07-22T14:15:27+00:00\",\"author\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/572a73e5111c709d73b211d71678f4b6\"},\"description\":\"Das Thema Test ist heute in der Softwareentwicklung ein grundlegender Bestandteil, um zu vermeiden, dass kritische Fehler erst beim Live-Betrieb auftauchen.\",\"breadcrumb\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/#primaryimage\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2017\/04\/201704_protractor_fi.png\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2017\/04\/201704_protractor_fi.png\",\"width\":1281,\"height\":734},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Protractor \u2013 Automatisiert Testen mit Angular\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/\",\"name\":\"Digital Innovation Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/572a73e5111c709d73b211d71678f4b6\",\"name\":\"Niels Brestrich\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2024\/01\/Mitarbeiterbild_Niels_2-e1706627343161-150x150.png\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2024\/01\/Mitarbeiterbild_Niels_2-e1706627343161-150x150.png\",\"caption\":\"Niels Brestrich\"},\"description\":\"Niels Brestrich arbeitet seit 2016 als Software Test Consultant f\u00fcr Zeiss Digital Innovation in Dresden. Seine Schwerpunkte sind das manuelle bzw. automatisierte Testen von Software f\u00fcr Mikroskope. Er arbeitet vorrangig mit .NET und Java f\u00fcr System bzw. UI-Tests.\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/nielsbrestrich\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Protractor - Automatisiert Testen mit Angular- ZEISS Digital Innovation Blog","description":"Das Thema Test ist heute in der Softwareentwicklung ein grundlegender Bestandteil, um zu vermeiden, dass kritische Fehler erst beim Live-Betrieb auftauchen.","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:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/","og_locale":"de_DE","og_type":"article","og_title":"Protractor - Automatisiert Testen mit Angular- ZEISS Digital Innovation Blog","og_description":"Das Thema Test ist heute in der Softwareentwicklung ein grundlegender Bestandteil, um zu vermeiden, dass kritische Fehler erst beim Live-Betrieb auftauchen.","og_url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/","og_site_name":"Digital Innovation Blog","article_publisher":"https:\/\/www.facebook.com\/ZEISSDigitalInnovation\/","article_published_time":"2017-04-06T13:21:29+00:00","article_modified_time":"2020-07-22T14:15:27+00:00","og_image":[{"width":1281,"height":734,"url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2017\/04\/201704_protractor_fi.png","type":"image\/png"}],"author":"Niels Brestrich","twitter_card":"summary_large_image","twitter_creator":"@ZEISS_di","twitter_site":"@ZEISS_di","twitter_misc":{"Verfasst von":"Niels Brestrich","Gesch\u00e4tzte Lesezeit":"9\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/","name":"Protractor - Automatisiert Testen mit Angular- ZEISS Digital Innovation Blog","isPartOf":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/#primaryimage"},"image":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2017\/04\/201704_protractor_fi.png","datePublished":"2017-04-06T13:21:29+00:00","dateModified":"2020-07-22T14:15:27+00:00","author":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/572a73e5111c709d73b211d71678f4b6"},"description":"Das Thema Test ist heute in der Softwareentwicklung ein grundlegender Bestandteil, um zu vermeiden, dass kritische Fehler erst beim Live-Betrieb auftauchen.","breadcrumb":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/#primaryimage","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2017\/04\/201704_protractor_fi.png","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2017\/04\/201704_protractor_fi.png","width":1281,"height":734},{"@type":"BreadcrumbList","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/protractor-automatisiert-testen-mit-angular\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/"},{"@type":"ListItem","position":2,"name":"Protractor \u2013 Automatisiert Testen mit Angular"}]},{"@type":"WebSite","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/","name":"Digital Innovation Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Person","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/572a73e5111c709d73b211d71678f4b6","name":"Niels Brestrich","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/image\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2024\/01\/Mitarbeiterbild_Niels_2-e1706627343161-150x150.png","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2024\/01\/Mitarbeiterbild_Niels_2-e1706627343161-150x150.png","caption":"Niels Brestrich"},"description":"Niels Brestrich arbeitet seit 2016 als Software Test Consultant f\u00fcr Zeiss Digital Innovation in Dresden. Seine Schwerpunkte sind das manuelle bzw. automatisierte Testen von Software f\u00fcr Mikroskope. Er arbeitet vorrangig mit .NET und Java f\u00fcr System bzw. UI-Tests.","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/nielsbrestrich\/"}]}},"author_meta":{"display_name":"Niels Brestrich","author_link":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/nielsbrestrich\/"},"featured_img":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2017\/04\/201704_protractor_fi-600x344.png","coauthors":[],"tax_additional":{"categories":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/qualitaetssicherung\/\" class=\"advgb-post-tax-term\">Qualit\u00e4tssicherung<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Web<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">Qualit\u00e4tssicherung<\/span>","<span class=\"advgb-post-tax-term\">Web<\/span>"]},"tags":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">quality assurance<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Qualit\u00e4tssicherung<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">automatisiertes Testen<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Testautomatisierung<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Protractor<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">quality assurance<\/span>","<span class=\"advgb-post-tax-term\">Qualit\u00e4tssicherung<\/span>","<span class=\"advgb-post-tax-term\">automatisiertes Testen<\/span>","<span class=\"advgb-post-tax-term\">Testautomatisierung<\/span>","<span class=\"advgb-post-tax-term\">Protractor<\/span>"]}},"comment_count":"0","relative_dates":{"created":"Posted 9\u00a0Jahren ago","modified":"Updated 6\u00a0Jahren ago"},"absolute_dates":{"created":"Posted on April 6, 2017","modified":"Updated on Juli 22, 2020"},"absolute_dates_time":{"created":"Posted on April 6, 2017 1:21 p.m.","modified":"Updated on Juli 22, 2020 2:15 p.m."},"featured_img_caption":"","series_order":"","_links":{"self":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1145","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/comments?post=1145"}],"version-history":[{"count":3,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1145\/revisions"}],"predecessor-version":[{"id":1177,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1145\/revisions\/1177"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/media\/1176"}],"wp:attachment":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/media?parent=1145"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/categories?post=1145"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/tags?post=1145"},{"taxonomy":"topics","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/topics?post=1145"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}