{"id":1293,"date":"2020-06-24T09:32:16","date_gmt":"2020-06-24T09:32:16","guid":{"rendered":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/?p=1293"},"modified":"2020-06-29T11:50:17","modified_gmt":"2020-06-29T11:50:17","slug":"pimp-my-testautomation-teil-2","status":"publish","type":"post","link":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/","title":{"rendered":"Pimp my testAUTOmation (Teil 2)"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\"><strong>Videos der Testdurchf\u00fchrung aufnehmen<\/strong><\/h2>\n\n\n\n<p>Mit dieser Blogreihe m\u00f6chte ich zeigen, wie sich mit einfachen Mitteln wichtige Funktionen in Selenium einbauen lassen. Im ersten Teil habe ich vorgestellt, was Selenium 4 bringt und wie Screenshots eingesetzt werden k\u00f6nnen. Im zweiten Teil erstellen wir ein Video der Testdurchf\u00fchrung. Dabei versuche ich, die Ans\u00e4tze nach ihrem Mehrwert (The Good) und ihren Herausforderungen (The Bad) zu bewerten und ggf. n\u00fctzliche Hinweise (&#8230; and the Useful) zu geben.<\/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\"><strong>Warum?<\/strong><\/h2>\n\n\n\n<p>Aber zum Anfang stellen wir uns kurz die Frage: Warum ein Video bzw. einen Screencast der Testdurchf\u00fchrung aufzeichnen?<\/p>\n\n\n\n<p>Mit einem Video haben wir eine Aufnahme des gesamten Testlaufs. Anders als mit einem Screenshot k\u00f6nnen wir so nicht nur das Testergebnis festhalten, sondern es l\u00e4sst sich auch der Weg dorthin nachvollziehen.<\/p>\n\n\n\n<p>Wie Screenshots k\u00f6nnen auch die Videos zum Debugging dienen und auf Probleme w\u00e4hrend des Testlaufes hinweisen. Darum ist es wie beim Screenshot sinnvoll, nur dann Videos zu erzeugen, wenn Probleme auftreten. Nach diesem Ansatz sollte die Video-Funktionalit\u00e4t um einen flexiblen und globalen Schalter erweitert werden, der sich je nach Notwendigkeit setzen l\u00e4sst.<\/p>\n\n\n\n<p>Aber die Videos k\u00f6nnen auch der Dokumentation der Testergebnisse dienen. In manchen Projekten ist eine ausf\u00fchrliche Dokumentation sogar verpflichtend vorgeschrieben, da hier gesetzliche oder andere Vorgaben eingehalten werden m\u00fcssen.<\/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\"><strong>Videos aufnehmen leicht gemacht<\/strong><\/h2>\n\n\n\n<p>Da ich Selenium mit der Java-Auspr\u00e4gung nutze, war mein erster Ansatz, Videos mit den &#8222;hauseigenen&#8220; Funktionen von Java aufzunehmen bzw. ein passendes Framework zu nutzen. Meine erste Wahl fiel auf das Framework MonteCC, da sich hier mit der Hilfe von nur zwei Methoden der Bildschirm w\u00e4hrend der Testdurchf\u00fchrung aufnehmen lie\u00df. In einer Methode vor dem Test wird die Videoaufnahme gestartet und in einer Methode nach dem Test wird die Aufnahme gestoppt und das Video im passenden Verzeichnis abgelegt.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code>private ScreenRecorder screenRecorder;\n \n@BeforeEach\npublic void beforeTest() {\n \n    GraphicsConfiguration gc = GraphicsEnvironment\n            .getLocalGraphicsEnvironment()\n            .getDefaultScreenDevice()\n            .getDefaultConfiguration();\n \n    try {\n        this.screenRecorder = new ScreenRecorder(gc,\n                new Format(MediaTypeKey, MediaType.FILE, MimeTypeKey, MIME_AVI),\n                new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,\n                        CompressorNameKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,\n                        DepthKey, 24, FrameRateKey, Rational.valueOf(15),\n                        QualityKey, 1.0f,\n                        KeyFrameIntervalKey, 15 * 60),\n                new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey,\"black\",\n                        FrameRateKey, Rational.valueOf(30)),\n                null);\n        this.screenRecorder.start();\n \n    } catch (Exception e) {\n        System.out.println(\"screenRecorder.start \" + e.getMessage());\n    }\n}\n \n@AfterEach\npublic void afterTest()  {\n \n    try {\n        this.screenRecorder.stop();\n        List createdMovieFiles = screenRecorder.getCreatedMovieFiles();\n        for (Object movie: createdMovieFiles) {\n            File m = (File)movie;\n            System.out.println(\"New movie created: \" + m.getAbsolutePath());\n        }\n \n    } catch (IOException ioe) {\n        System.out.println(\"screenRecorder.stop \" + ioe.getMessage());\n    }\n}<\/code><\/pre>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Damit dies vor jedem Test passiert, nutzen wir die Annotations von JUnit:<\/p>\n\n\n\n<p><em><strong>@Test<\/strong><\/em><\/p>\n\n\n\n<p><em>Die Methode mit der Annotation @Test ist ein Testfall und wird bei der Testausf\u00fchrung gestartet und das Ergebnis im Testprotokoll erfasst.<\/em><\/p>\n\n\n\n<p><em><strong>@BeforeEach<\/strong><\/em><\/p>\n\n\n\n<p><em>Diese Methode wird vor jeder Testauff\u00fchrung aufgerufen (siehe @Test).<\/em><\/p>\n\n\n\n<p><em><strong>@AfterEach<\/strong><\/em><\/p>\n\n\n\n<p><em>Diese Methode wird nach jeder Testauff\u00fchrung aufgerufen (siehe @Test).<\/em><\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Wer eine komplette Aufzeichnung aller Testf\u00e4lle ben\u00f6tigt, kann auch die Annotations @Before und @After nutzen, die vor allen bzw. nach allen Tests einer Testsuite (Testklasse) aufgerufen werden.<\/p>\n\n\n\n<p>Gro\u00dfe Nachteile von MonteCC sind, dass zum einen das letzte Release bereits mehr als sechs Jahre zur\u00fcckliegt und zum anderen, dass die Videos im Format QuickTime vorliegen.<\/p>\n\n\n\n<p>Als Alternative bot sich JavaCV (<a href=\"https:\/\/github.com\/bytedeco\/javacv\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/bytedeco\/javacv<\/a>) an. Die Bibliothek wird in GitHub flei\u00dfig gepflegt und speichert Videos im Format MPEG. Auch hier gibt es bei der Videoerzeugung zwei Methoden, die sowohl vor als auch nach dem Test aufgerufen werden k\u00f6nnen. Aber die JavaCV ben\u00f6tigt weitere Methoden, da parallel zum Testlauf in kurzen Abst\u00e4nden Screenshots erstellt und diese dann nach dem Test zu einem Video zusammenstellt werden. Eine ausf\u00fchrliche Anleitung findet ihr unter folgenden Link: <a href=\"https:\/\/cooltrickshome.blogspot.com\/2016\/12\/create-your-own-free-screen-recorder.html\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/cooltrickshome.blogspot.com\/2016\/12\/create-your-own-free-screen-recorder.html<\/a>.<\/p>\n\n\n\n<p>F\u00fcr den Einsatz beim automatisierten Testen habe ich folgende \u00c4nderungen vorgenommen:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n *\n * https:\/\/github.com\/bytedeco\/javacv\n * https:\/\/cooltrickshome.blogspot.com\/2016\/12\/create-your-own-free-screen-recorder.html\n *\/\npublic class RecordSeleniumJavaCV {\n \n    \/\/ The WebDriver is a tool for writing automated tests of websites.\n    FirefoxDriver driver;\n \n    public static boolean videoComplete=false;\n    public static String inputImageDir= \"videos\" + File.separator + \"inputImgFolder\"+File.separator;\n    public static String inputImgExt=\"png\";\n    public static String outputVideoDir= \"videos\" + File.separator;\n    public static String outputVideo;\n    public static int counter=0;\n    public static int imgProcessed=0;\n    public static FFmpegFrameRecorder recorder=null;\n    public static int videoWidth=1920;\n    public static int videoHeight=1080;\n    public static int videoFrameRate=3;\n    public static int videoQuality=0; \/\/ 0 is the max quality\n    public static int videoBitRate=9000;\n    public static String videoFormat=\"mp4\";\n    public static int videoCodec=avcodec.AV_CODEC_ID_MPEG4;\n    public static Thread t1=null;\n    public static Thread t2=null;\n    public static boolean isRegionSelected=false;\n    public static int c1=0;\n    public static int c2=0;\n    public static int c3=0;\n    public static int c4=0;\n \n    \/**\n     * Explanation:\n     * 1) videoComplete variables tells if user has stopped the recording or not.\n     * 2) inputImageDir defines the input directory where screenshots will be stored which would be utilized by the video thread\n     * 3) inputImgExt denotes the extension of the image taken for screenshot.\n     * 4) outputVideo is the name of the recorded video file\n     * 5) counter is used for numbering the screenshots when stored in input directory.\n     * 6) recorder is used for starting and stopping the video recording\n     * 7) videoWidth, videoFrameRate etc define output video param\n     * 8) If user wants to record only a selected region then c1,c2,c3,c4 denotes the coordinate\n     *\n     * @return\n     * @throws Exception\n     *\/\n    public static FFmpegFrameRecorder getRecorder() throws Exception\n    {\n        if(recorder!=null)\n        {\n            return recorder;\n        }\n        recorder = new FFmpegFrameRecorder(outputVideo,videoWidth,videoHeight);\n        try\n        {\n            recorder.setFrameRate(videoFrameRate);\n            recorder.setVideoCodec(videoCodec);\n            recorder.setVideoBitrate(videoBitRate);\n            recorder.setFormat(videoFormat);\n            recorder.setVideoQuality(videoQuality); \/\/ maximum quality\n            recorder.start();\n        }\n        catch(Exception e)\n        {\n            System.out.println(\"Exception while starting the recorder object \"+e.getMessage());\n            throw new Exception(\"Unable to start recorder\");\n        }\n        return recorder;\n    }\n \n    \/**\n     * Explanation:\n     * 1) This method is used to get the Recorder object.\n     * 2) We create an object of FFmpegFrameRecorder named \"Recorder\" and then set all its video parameters.\n     * 3) Lastly we start the recorder and then return the object.\n     *\n     * @return\n     * @throws Exception\n     *\/\n    public static Robot getRobot() throws Exception\n    {\n        Robot r=null;\n        try {\n            r = new Robot();\n            return r;\n        } catch (AWTException e) {\n            System.out.println(\"Issue while initiating Robot object \"+e.getMessage());\n            throw new Exception(\"Issue while initiating Robot object\");\n        }\n    }\n \n    \/**\n     * Explanation:\n     * 1) Two threads are started in this module when user starts the recording\n     * 2) First thread calls the takeScreenshot module which keeps on taking screenshot of user screen and saves them on local disk.\n     * 3) Second thread calls the prepareVideo which monitors the screenshot created in step 2 and add them continuously on the video.\n     *\n     * @param r\n     *\/\n    public static void takeScreenshot(Robot r)\n    {\n        Dimension size = Toolkit.getDefaultToolkit().getScreenSize();\n        Rectangle rec=new Rectangle(size);\n        if(isRegionSelected)\n        {\n            rec=new Rectangle(c1, c2, c3-c1, c4-c2);\n        }\n        while(!videoComplete)\n        {\n            counter++;\n            BufferedImage img = r.createScreenCapture(rec);\n            try {\n                ImageIO.write(img, inputImgExt, new File(inputImageDir+counter+\".\"+inputImgExt));\n            } catch (IOException e) {\n                System.out.println(\"Got an issue while writing the screenshot to disk \"+e.getMessage());\n                counter--;\n            }\n        }\n    }\n \n    \/**\n     * Explanation:\n     * 1) If user has selected a region for recording then we set the rectangle with the coordinate value of c1,c2,c3,c4. Otherwise we set the rectangle to be full screen\n     * 2) Now we run a loop until videoComplete is false (remains false until user press stop recording.\n     * 3) Now we capture the region and write the same to the input image directory.\n     * 4) So when user starts the recording this method keeps on taking screenshot and saves them into disk.\n     *\n     *\/\n    public static void prepareVideo()\n    {\n        File scanFolder=new File(inputImageDir);\n        while(!videoComplete)\n        {\n            File&#91;] inputFiles=scanFolder.listFiles();\n            try {\n                getRobot().delay(500);\n            } catch (Exception e) {\n            }\n            \/\/for(int i=0;i&lt;scanFolder.list().length;i++)\n            for(int i=0;i&lt;inputFiles.length;i++)\n            {\n                \/\/imgProcessed++;\n                addImageToVideo(inputFiles&#91;i].getAbsolutePath());\n                \/\/String imgToAdd=scanFolder.getAbsolutePath()+File.separator+imgProcessed+\".\"+inputImgExt;\n                \/\/addImageToVideo(imgToAdd);\n                \/\/new File(imgToAdd).delete();\n                inputFiles&#91;i].delete();\n            }\n        }\n        File&#91;] inputFiles=scanFolder.listFiles();\n        for(int i=0;i&lt;inputFiles.length;i++)\n        {\n            addImageToVideo(inputFiles&#91;i].getAbsolutePath());\n            inputFiles&#91;i].delete();\n        }\n    }\n \n    \/**\n     * Explanation:\n     * 1) cvLoadImage is used to load the image passed as argument\n     * 2) We call the convert method to convert the image to frame which could be used by the recorder\n     * 3) We pass the frame obtained in step 2 and add the same in the recorder by calling the record method.\n     *\n     * @return\n     *\/\n    public static OpenCVFrameConverter.ToIplImage getFrameConverter()\n    {\n        OpenCVFrameConverter.ToIplImage grabberConverter = new OpenCVFrameConverter.ToIplImage();\n        return grabberConverter;\n    }\n \n    \/**\n     * Explanation:\n     * 1) We start a loop which will run until video complete is set true (done only when user press stop recording)\n     * 2) We keep on monitoring the input  Image directory\n     * 3) We traverse each file found in the input image directory and add those images to video using the addImageToVideo method. After the image has been added we delete the image\n     * 4) Using the loop in step1 we keep on repeating step 2 and 3 so that each image gets added to video. We added a delay of 500ms so that this module does not picks a half created image from the takeScreenshot module\n     * 5) When user press stop recording the loop gets broken. Now we finally traverse the input image directory and add the remaining images to video.\n     *\n     * @param imgPath\n     *\/\n    public static void addImageToVideo(String imgPath)\n    {\n        try {\n            getRecorder().record(getFrameConverter().convert(cvLoadImage(imgPath)));\n        } catch (Exception e) {\n            System.out.println(\"Exception while adding image to video \"+e.getMessage());\n        }\n    }\n \n    \/**\n     * Explanation:\n     * 1) We make a JFrame with the button for staring and stopping the recording. One more button is added for allowing user to record only a selected portion of screen\n     * 2) If user clicks to select only certain region then we call a class CropRegion method getImage which helps in retrieving the coordinate of the region selected by user and update the same in variable c1,c2,c3,c4\n     * 3) If user clicks on start recording then startRecording method is called\n     * 4) If user clicks on stoprecording then stopRecording method is called\n     *\/\n    @BeforeEach\n    public void beforeTest() {\n \n        System.out.println(\"this.screenRecorder.start()\");\n \n        SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyyMMdd_HHmmss\");\n        String timestamp  = dateFormat.format(new Date());\n \n        outputVideo= outputVideoDir + \"recording_\" + timestamp + \".mp4\";\n \n        try {\n            t1=new Thread()\n            {\n                public void run() {\n                    try {\n                        takeScreenshot(getRobot());\n                    } catch (Exception e) {\n                        System.out.println(\"Cannot make robot object, Exiting program \"+e.getMessage());\n                        System.exit(0);\n                    }\n                }\n            };\n            t2=new Thread()\n            {\n                public void run() {\n                    prepareVideo();\n                }\n            };\n            t1.start();\n            t2.start();\n            System.out.println(\"Started recording at \"+new Date());\n \n \n        } catch (Exception e) {\n            System.out.println(\"screenRecorder.start \" + e.getMessage());\n        }\n    }\n \n    @AfterEach\n    public void afterTest()  {\n \n        System.out.println(\"this.screenRecorder.stop()\");\n \n        try {\n            videoComplete=true;\n            System.out.println(\"Stopping recording at \"+new Date());\n            t1.join();\n            System.out.println(\"Screenshot thread complete\");\n            t2.join();\n            System.out.println(\"Video maker thread complete\");\n            getRecorder().stop();\n            System.out.println(\"Recording has been saved successfully at \"+new File(outputVideo).getAbsolutePath());\n \n        } catch (Exception e) {\n            System.out.println(\"screenRecorder.stop \" + e.getMessage());\n        }\n    }\n \n    @Test\n    public void testMe() {\n         \n        \/\/toDo\n \n    }\n \n}<\/code><\/pre>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Gibt es einen Haken?<\/h2>\n\n\n\n<p>Somit haben wir nun mehrere M\u00f6glichkeiten, den automatischen Testlauf in einem Video festzuhalten, um bei Problemen diese nachvollziehen oder die Dokumentationspflichten erf\u00fcllen zu k\u00f6nnen.<\/p>\n\n\n\n<p>Aber die Aufnahme w\u00e4hrend des Testdurchlaufes ist mit einem Risiko verbunden, dass der Tester \/ Testautomatisierer beachten sollte: Es ist ein Eingriff den normalen Testablauf, da wir ggf. die Timings der Geschwindigkeit \u00e4ndern. Unser modifizierter Testlauf mit Videoaufnahme kann sich anders verhalten als ein Testlauf ohne Videoaufnahme.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"has-text-align-center\"><strong>Videos der Testdurchf\u00fchrung<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-table is-style-regular\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>The Good<\/strong><\/td><td><strong>The Bad<\/strong><\/td><td><strong>&#8230; and the Useful<\/strong><\/td><\/tr><tr><td>\u2022 Aufnahme des gesamten Testlaufs<br>\u2022 Neben dem Testergebnis l\u00e4sst sich auch der Weg dorthin nachvollziehen<br><br><\/td><td>\u2022 Es wird der Testlauf beeinflusst<br>\u2022 Verschiedene alte und kostenpflichtige Frameworks zur Videoaufnahme<br>\u2022 Codecs Probleme (nur QuicktimeView)<\/td><td>\u2022 JavaCV \u2192<br><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/bytedeco\/javacv\" target=\"_blank\">github.com\/bytedeco\/javacv<\/a><br><br><br><br><br><\/td><\/tr><\/tbody><\/table><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Im zweiten Teil der Blogreihe zu Selenium 4 erstellen wir ein Video der Testdurchf\u00fchrung. <\/p>\n","protected":false},"author":13,"featured_media":1173,"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],"tags":[328,464,466,467,468,469,52],"topics":[227],"class_list":["post-1293","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-qualitaetssicherung","tag-selenium","tag-selenium-4","tag-debugging","tag-montecc","tag-junit-annotations","tag-javacv","tag-testautomatisierung","topics-testautomatisierung"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Pimp my testAUTOmation (Teil 2) - ZEISS Digital Innovation Blog<\/title>\n<meta name=\"description\" content=\"Im zweiten Teil der Blogreihe rund um die Erweiterung von Funktionen in Selenium 4 erstellen wir ein Video der Testdurchf\u00fchrung.\" \/>\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\/pimp-my-testautomation-teil-2\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Pimp my testAUTOmation (Teil 2) - ZEISS Digital Innovation Blog\" \/>\n<meta property=\"og:description\" content=\"Im zweiten Teil der Blogreihe rund um die Erweiterung von Funktionen in Selenium 4 erstellen wir ein Video der Testdurchf\u00fchrung.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/\" \/>\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=\"2020-06-24T09:32:16+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-06-29T11:50:17+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/06\/202006_pimp_my_testautomation.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"806\" \/>\n\t<meta property=\"og:image:height\" content=\"439\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Kay Grebenstein\" \/>\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=\"Kay Grebenstein\" \/>\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\/pimp-my-testautomation-teil-2\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/\",\"name\":\"Pimp my testAUTOmation (Teil 2) - ZEISS Digital Innovation Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/06\/202006_pimp_my_testautomation.jpg\",\"datePublished\":\"2020-06-24T09:32:16+00:00\",\"dateModified\":\"2020-06-29T11:50:17+00:00\",\"author\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/cce7b67c4207708837bcfd4500b2bbf9\"},\"description\":\"Im zweiten Teil der Blogreihe rund um die Erweiterung von Funktionen in Selenium 4 erstellen wir ein Video der Testdurchf\u00fchrung.\",\"breadcrumb\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/#primaryimage\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/06\/202006_pimp_my_testautomation.jpg\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/06\/202006_pimp_my_testautomation.jpg\",\"width\":806,\"height\":439},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Pimp my testAUTOmation (Teil 2)\"}]},{\"@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\/cce7b67c4207708837bcfd4500b2bbf9\",\"name\":\"Kay Grebenstein\",\"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\/2020\/05\/grebenstein_kay-150x150.jpg\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/05\/grebenstein_kay-150x150.jpg\",\"caption\":\"Kay Grebenstein\"},\"description\":\"Kay Grebenstein arbeitete als langj\u00e4hriger Tester und agiler QA-Coach f\u00fcr die ZEISS Digital Innovation, Dresden. Er sicherte in Projekten unterschiedlicher fachlicher Dom\u00e4nen (Telekommunikation, Industrie, Versandhandel, Energie, \u2026) Qualit\u00e4t und testete Software. Seine Erfahrungen teilt er weiterhin auf Konferenzen, Meetups und in Ver\u00f6ffentlichungen unterschiedlicher Art.\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/kaygrebenstein\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Pimp my testAUTOmation (Teil 2) - ZEISS Digital Innovation Blog","description":"Im zweiten Teil der Blogreihe rund um die Erweiterung von Funktionen in Selenium 4 erstellen wir ein Video der Testdurchf\u00fchrung.","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\/pimp-my-testautomation-teil-2\/","og_locale":"de_DE","og_type":"article","og_title":"Pimp my testAUTOmation (Teil 2) - ZEISS Digital Innovation Blog","og_description":"Im zweiten Teil der Blogreihe rund um die Erweiterung von Funktionen in Selenium 4 erstellen wir ein Video der Testdurchf\u00fchrung.","og_url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/","og_site_name":"Digital Innovation Blog","article_publisher":"https:\/\/www.facebook.com\/ZEISSDigitalInnovation\/","article_published_time":"2020-06-24T09:32:16+00:00","article_modified_time":"2020-06-29T11:50:17+00:00","og_image":[{"width":806,"height":439,"url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/06\/202006_pimp_my_testautomation.jpg","type":"image\/jpeg"}],"author":"Kay Grebenstein","twitter_card":"summary_large_image","twitter_creator":"@ZEISS_di","twitter_site":"@ZEISS_di","twitter_misc":{"Verfasst von":"Kay Grebenstein","Gesch\u00e4tzte Lesezeit":"9\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/","name":"Pimp my testAUTOmation (Teil 2) - ZEISS Digital Innovation Blog","isPartOf":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/#primaryimage"},"image":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/06\/202006_pimp_my_testautomation.jpg","datePublished":"2020-06-24T09:32:16+00:00","dateModified":"2020-06-29T11:50:17+00:00","author":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/cce7b67c4207708837bcfd4500b2bbf9"},"description":"Im zweiten Teil der Blogreihe rund um die Erweiterung von Funktionen in Selenium 4 erstellen wir ein Video der Testdurchf\u00fchrung.","breadcrumb":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/#primaryimage","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/06\/202006_pimp_my_testautomation.jpg","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/06\/202006_pimp_my_testautomation.jpg","width":806,"height":439},{"@type":"BreadcrumbList","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/pimp-my-testautomation-teil-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/"},{"@type":"ListItem","position":2,"name":"Pimp my testAUTOmation (Teil 2)"}]},{"@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\/cce7b67c4207708837bcfd4500b2bbf9","name":"Kay Grebenstein","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\/2020\/05\/grebenstein_kay-150x150.jpg","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/05\/grebenstein_kay-150x150.jpg","caption":"Kay Grebenstein"},"description":"Kay Grebenstein arbeitete als langj\u00e4hriger Tester und agiler QA-Coach f\u00fcr die ZEISS Digital Innovation, Dresden. Er sicherte in Projekten unterschiedlicher fachlicher Dom\u00e4nen (Telekommunikation, Industrie, Versandhandel, Energie, \u2026) Qualit\u00e4t und testete Software. Seine Erfahrungen teilt er weiterhin auf Konferenzen, Meetups und in Ver\u00f6ffentlichungen unterschiedlicher Art.","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/kaygrebenstein\/"}]}},"author_meta":{"display_name":"Kay Grebenstein","author_link":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/kaygrebenstein\/"},"featured_img":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/06\/202006_pimp_my_testautomation-600x327.jpg","coauthors":[],"tax_additional":{"categories":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/qualitaetssicherung\/\" class=\"advgb-post-tax-term\">Qualit\u00e4tssicherung<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">Qualit\u00e4tssicherung<\/span>"]},"tags":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/qualitaetssicherung\/\" class=\"advgb-post-tax-term\">Selenium<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/qualitaetssicherung\/\" class=\"advgb-post-tax-term\">Selenium 4<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/qualitaetssicherung\/\" class=\"advgb-post-tax-term\">Debugging<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/qualitaetssicherung\/\" class=\"advgb-post-tax-term\">MonteCC<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/qualitaetssicherung\/\" class=\"advgb-post-tax-term\">JUnit Annotations<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/qualitaetssicherung\/\" class=\"advgb-post-tax-term\">JavaCV<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/qualitaetssicherung\/\" class=\"advgb-post-tax-term\">Testautomatisierung<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">Selenium<\/span>","<span class=\"advgb-post-tax-term\">Selenium 4<\/span>","<span class=\"advgb-post-tax-term\">Debugging<\/span>","<span class=\"advgb-post-tax-term\">MonteCC<\/span>","<span class=\"advgb-post-tax-term\">JUnit Annotations<\/span>","<span class=\"advgb-post-tax-term\">JavaCV<\/span>","<span class=\"advgb-post-tax-term\">Testautomatisierung<\/span>"]}},"comment_count":"0","relative_dates":{"created":"Posted 6\u00a0Jahren ago","modified":"Updated 6\u00a0Jahren ago"},"absolute_dates":{"created":"Posted on Juni 24, 2020","modified":"Updated on Juni 29, 2020"},"absolute_dates_time":{"created":"Posted on Juni 24, 2020 9:32 a.m.","modified":"Updated on Juni 29, 2020 11:50 a.m."},"featured_img_caption":"","series_order":"","_links":{"self":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1293","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\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/comments?post=1293"}],"version-history":[{"count":11,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1293\/revisions"}],"predecessor-version":[{"id":1337,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1293\/revisions\/1337"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/media\/1173"}],"wp:attachment":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/media?parent=1293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/categories?post=1293"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/tags?post=1293"},{"taxonomy":"topics","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/topics?post=1293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}