Problem: when running long selenium scripts, browser process eats memory like a hungry boa.
Cause: selenium does not release events attached to tested app objects.
Solution: register attached events and release them on page unloads. Idea was found at http://novemberborn.net/javascript/event-cache
Patch:
You need to add eventcache.js (http://novemberborn.net/javascript/event-cache.js
, also provided here) to your selenium directory and patch some selenium files:
--------------------------------------- eventcache.js (add) start ---------------------------------------
/* EventCache Version 1.0
Copyright 2005 Mark Wubben
Provides a way for automagically removing events from nodes and thus preventing memory leakage.
See <http://novemberborn.net/javascript/event-cache
> for more information.
This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/
>
*/
//window.alert ("Event_Cache.js!");
/* Implement array.push for browsers which don't support it natively.
Please remove this if it's already in other code */
if(Array.prototype.push == null){
Array.prototype.push = function(){
for(var i = 0; i < arguments.length; i++){
this[this.length] = arguments[i];
};
return this.length;
};
};
/* Event Cache uses an anonymous function to create a hidden scope chain.
This is to prevent scoping issues. */
var EventCache = function(){
var listEvents = [];
return {
listEvents : listEvents,
add : function(node, sEventName, fHandler, bCapture){
listEvents.push(arguments);
},
flush : function(){
var i, item;
for(i = listEvents.length - 1; i >= 0; i = i - 1){
item = listEvents[i];
if(item[0].removeEventListener){
item[0].removeEventListener(item[1], item[2], item[3]);
};
/* From this point on we need the event names to be prefixed with 'on" */
if(item[1].substring(0, 2) != "on"){
item[1] = "on" + item[1];
};
if(item[0].detachEvent){
item[0].detachEvent(item[1], item[2]);
};
item[0][item[1]] = null;
};
}
};
}();
--------------------------------------- eventcache.js (add) end ---------------------------------------
--------------------------------------- selenium-browserbot.js (edit) start ---------------------------------------
// line 228
BrowserBot.prototype.callOnWindowPageTransition = function(loadFunction, windowObject) {
var attachLoadListener = function() {
if (windowObject && !windowObject.closed) {
addLoadListener(windowObject, loadFunction);
}
};
var unloadFunction = function() {
window.setTimeout(attachLoadListener, 0);
};
addUnloadListener(windowObject, unloadFunction);
// patch start
addEvent(windowObject, "unload", EventCache.flush);
// patch end
};
//.....................................//
// line 715 (inside MozillaPageBot.prototype.clickElement() )
if (geckoVersion) {
element.addEventListener("click", function(evt) {preventDefault = evt.getPreventDefault();}, false);
// patch start
EventCache.add(node, "propertychange", onPropertyChangeEventHandler);
// patch end
}
--------------------------------------- selenium-browserbot.js (edit) end ---------------------------------------
--------------------------------------- html-xpath-patched.js (edit) start ---------------------------------------
// line 593 ( near end of function loadNode(dom, domParentNode, node, helper) )
node.attachEvent("onpropertychange", onPropertyChangeEventHandler);
// patch start
EventCache.add(node, "propertychange", onPropertyChangeEventHandler);
// patch end
}
}
--------------------------------------- html-xpath-patched.js (edit) end ---------------------------------------
--------------------------------------- htmlutils.js (edit) start ---------------------------------------
// line 103
function addLoadListener(element, command) {
if (window.addEventListener)
element.addEventListener("load",command, true);
else if (window.attachEvent)
element.attachEvent("onload",command);
// patch start
EventCache.add(element, "load",command, true);
// patch end
}
function addUnloadListener(element, command) {
if (window.addEventListener)
element.addEventListener("unload",command, true);
else if (window.attachEvent)
element.attachEvent("onunload",command);
// patch start
EventCache.add(element, "unload",command, true);
// patch end
}
--------------------------------------- htmlutils.js (edit) end ---------------------------------------
--------------------------------------- TestRunner.html (edit) start ---------------------------------------
<!-- line 29 -->
<!-- patch start -->
<script language="JavaScript" type="text/javascript" src="event-cache.js"></script>
<!-- patch end -->
--------------------------------------- TestRunner.html (edit) end ---------------------------------------
I guess this is out of date. I tried to apply this patch on 1.0.Beta.2
I have some problems finding the first patch.
1.
— selenium-browserbot.js —
// line 228
BrowserBot.prototype.callOnWindowPageTransition = function(loadFunction, windowObject) {
var attachLoadListener = function() {
if (windowObject && !windowObject.closed) { addLoadListener(windowObject, loadFunction); }
};
var unloadFunction = function() { window.setTimeout(attachLoadListener, 0); };
addUnloadListener(windowObject, unloadFunction);
// patch start
addEvent(windowObject, "unload", EventCache.flush);
// patch end
};
2.
html-xpath-patched.js does not exist.
3. Unloadlistener doesn't exist in htmlutils.js