One problem with selenium (using either IDE, RC or Webdriver) is that you don't know what actually happened during the execution.
The selenium result would give some hints, e.g. if the verifyTextPresent
failed then you know there is a missing text during execution. But you would like to know what actually appears on that screen? Did the page show up an error page? Or just the value is changed, or probably the server died?
The nature of automated testing is that you are unlikely to watch the executions all the time. Otherwise it's pointless to do the automation.
My first approach is to use camstudio to do screen recording every night, so if there are some problems we could just check back the videos. But there are two major problems:
-
the video is quite long, it took a lot of time to find out what's going on in that particular moment.
-
during the execution, the browser size is actually halved (the other half is for the selenium runner), so you are unlikely to see the full screen during the run. This problem is even worse when you try to execute multiple testings in parallel.
So later, I switched to the second approach - use screen capture of firefox. I found that the selenium does support some sort of screenCapture internally. What I need to do is just extract and trigger the particular code snippet.
Source Code
Due to the architecture of Selenium, the source code of firefox screen capture could be found in two possible places:
-
extract the source code from selenium IDE plugin
- download the Selenium IDE plugin from firefox
- check the downloaded plugin folder
- unzip the plugin
For simplicity, I just collected the source code from the repository. After the source code is found, you only need to do:
grep -ir screenCaputre *
Then you would see the corresponding part of screenCapture. You could copy the corresponding code to the user-extensions.js
, and you would be able to use it.
However, trying to trigger it during the error is another story. You are going to change the following four functions. Two for Selenium IDE, and two for Selenium Server.
HtmlRunnerTestLoop.prototype.resume HtmlRunnerTestLoop.prototype.continueTestWhenConditionIsTrue TestLoop.prototype.resume TestLoop.prototype.continueTestWhenConditionIsTrue
In short, you need to add the followings to the end of user-extensions.js
. (Sorry for the messy debug messages 🙂 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
//get screenshot function doScreenShot(file_path) { if(jQuery.browser.msie) //for IE { //window.Snapsie.saveSnapshot(file_path); //not yet stable //selenium.doCaptureScreenshot(file_path); //selenium.doCaptureEntirePageScreenshot(file_path); } else selenium.doCaptureEntirePageScreenshot(file_path); } //make sure screenshot take place when error occurs function resumeOverride(){ LOG.info("@9217, on resume"); LOG.info("@9218, on resume"); /** * Select the next command and continue the test. */ LOG.debug("currentTest.resume() - actually execute"); try { selenium.browserbot.pageLoadError=null; selenium.browserbot.runScheduledPollers(); if(this.currentCommand.command == "open"){ var timestamp = makeStamp(new Date()); var connector = "?"; if(this.currentCommand.target.indexOf("?") >= 0) connector = "&"; var timestamp_argument = connector + "sel_timestamp=" + timestamp; this.currentCommand.target += timestamp_argument; LOG.info("@9539: adding time stamp to URL: " + this.currentCommand.target); } LOG.info("@9321"); this._executeCurrentCommand(); try { LOG.info("@9534"); var currentWindow = selenium.browserbot.getCurrentWindow(); LOG.info("@9537"); if(!g_resize_window_done && currentWindow && false){ currentWindow.moveTo(0, 0); currentWindow.resizeTo("1024", "800"); g_resize_window_done = true; } LOG.info("@9544"); // LOG.info("@9326"); var suite_file_name = ""; suite_file_name = getQueryVariable(currentWindow.location, "sel_suit"); LOG.info("@9313, current URL: " +currentWindow.location.href); if (suite_file_name || current_job_name){ current_suite_case_log(); } LOG.info("@9555"); } catch(e) { LOG.error("@9342, failed to get current screen log"); } if(this.result.failed) { LOG.error("@9201:failed"); //var command = this.currentCommand; //screenCapture(command.command + "|" + command.target + "|" + command.value) screenCaptureWithCommand(this.currentCommand); } this.continueTestWhenConditionIsTrue(); } catch (e) { LOG.error("@9210:" + e); //var command = this.currentCommand; //screenCapture(command.command + "|" + command.target + "|" + command.value) screenCaptureWithCommand(this.currentCommand); if (!this._handleCommandError(e)) { this.testComplete(); } else { this.continueTest(); } } } function continueTestWhenConditionIsTrueOverride(){ /** * Busy wait for waitForCondition() to become true, and then carry * on with test. Fail the current test if there's a timeout or an * exception. */ //LOG.debug("currentTest.continueTestWhenConditionIsTrue()"); selenium.browserbot.runScheduledPollers(); try { if (this.waitForCondition == null) { LOG.debug("null condition; let's continueTest()"); LOG.debug("Command complete"); this.commandComplete(this.result); this.continueTest(); } else if (this.waitForCondition()) { LOG.debug("condition satisfied; let's continueTest()"); this.waitForCondition = null; LOG.debug("Command complete"); this.commandComplete(this.result); this.continueTest(); } else { //LOG.debug("waitForCondition was false; keep waiting!"); window.setTimeout(fnBind(this.continueTestWhenConditionIsTrue, this), 10); } } catch (e) { this.result = {}; var errorMessage = extractExceptionMessage(e); //LOG.info("@9302: " + errorMessage); if(errorMessage.indexOf("MA_TIME_OUT") < 0 ){ this.result.failed = true; this.result.failureMessage = errorMessage; } else { LOG.info("skip error for MA_TIME_OUT"); } this.commandComplete(this.result); this.continueTest(); } } //for firefox IDE runner if( typeof HtmlRunnerTestLoop == 'function'){ HtmlRunnerTestLoop.prototype.resume = resumeOverride; HtmlRunnerTestLoop.prototype.continueTestWhenConditionIsTrue = continueTestWhenConditionIsTrueOverride; } //for selenium standalone server if( typeof TestLoop == 'function'){ TestLoop.prototype.resume = resumeOverride; TestLoop.prototype.continueTestWhenConditionIsTrue = continueTestWhenConditionIsTrueOverride; } |
One may get the full source code from here:
https://github.com/motherapp/enhanced-selenium-user-extensions
Leave a comment