Commit 0a1a952f authored by Jérome Perrin's avatar Jérome Perrin

tests: remove old way of running functional tests

parent ae59d7cd
#!/usr/bin/env python2.7
import os
import re
import signal
import sys
import shutil
import getopt
from time import sleep
import urllib2
from subprocess import Popen, PIPE
from sendMail import sendMail
import atexit
print "DEPRECATION WARNING: This command 'runFunctionalTest' is Deprecated, " + \
"you should use ERP5TypeFunctionalTestCase and runUnitTest instead." + \
"You can take a look at testFunctionalCore.py"
__doc__ = """%(program)s: Zelenium functional test runner for the ERP5 Project
usage: %(program)s [options]
Options:
-h, --help this help screen
--email_to_address=STRING send results to this address by email (defaults to
erp5-report@erp5.org)
--smtp_host=hostname specify SMTP server
-s, --stdout print the results on stdout instead of sending
results by email (unless email_to_address is also
passed explicitly)
-d, --debug run firefox on current DISPLAY instead of on Xvfb
--host the hostname of this ERP5 instance
--port the port of this ERP5 instance
--portal_name the ID of the ERP5 site
URLs will start with:
http://${host}:${port}/${portal_name}/
--run_only=STRING run only specified test suite (should be only one)
--email_subject the email subject to be sent
--xvfb_display=STRING Define a xvfb display to be used.
Notes:
* You need to prepare first test environment by using following command:
./runUnitTest.py --save prepareFunctionalTest.py
"""
tests_framework_home = os.path.dirname(os.path.abspath(__file__))
# handle 'system global' instance
if tests_framework_home.startswith('/usr/lib'):
real_instance_home = '/var/lib/erp5'
else:
real_instance_home = os.path.sep.join(
tests_framework_home.split(os.path.sep)[:-3])
instance_home = os.path.join(real_instance_home, 'unit_test')
bt5_dir_list = ','.join([
os.path.join(instance_home, 'Products/ERP5/bootstrap'),
os.path.join(instance_home, 'bt5')])
class FunctionalTestRunner:
"""
Used to run Functional tests
"""
def __init__(self, instance_home):
self.instance_home = instance_home
self.xvfb_fbdir = instance_home
self.send_mail = 0
self.stdout = 0
self.debug = 0
self.email_to_address = 'erp5-report@erp5.org'
self.smtp_host = ''
self.host = 'localhost'
self.port = 8080
self.user = 'ERP5TypeTestCase'
self.password = ''
self.portal_name = 'erp5_portal'
self.run_only = ''
self.email_subject = 'ERP5'
self.xvfb_display = '123'
self.profile_dir = os.path.join(instance_home, 'profile')
def usage(self, stream, msg=None):
if msg:
print >>stream, msg
print >>stream
program = os.path.basename(sys.argv[0])
print >>stream, __doc__ % {"program": program}
def parseArgs(self, arguments=None):
if arguments is None:
arguments = sys.argv[1:]
try:
opts, args = getopt.getopt(arguments,
"hsd", ["help", "stdout", "debug",
"email_to_address=", "host=", "port=",
"portal_name=", "run_only=", "user=",
"password=", "alarms=",
"email_subject=", "smtp_host=", "xvfb_display="] )
except getopt.GetoptError, msg:
self.usage(sys.stderr, msg)
sys.exit(2)
for opt, arg in opts:
if opt in ("-s", "--stdout"):
self.stdout = 1
elif opt in ("-d", "--debug"):
self.debug = 1
elif opt == '--email_to_address':
self.email_to_address = arg
self.send_mail = 1
elif opt == '--smtp_host':
self.smtp_host = arg
elif opt in ('-h', '--help'):
self.usage(sys.stdout)
sys.exit()
elif opt == "--host":
self.host = arg
elif opt == "--port":
self.port = int(arg)
elif opt == "--portal_name":
self.portal_name = arg
elif opt == "--run_only":
self.run_only = arg
elif opt == "--user":
user = arg
elif opt == "--password":
password = arg
elif opt == "--email_subject":
self.email_subject = arg
elif opt == "--xvfb_display":
self.xvfb_display = arg
if not self.stdout:
self.send_mail = 1
self.portal_url = "http://%s:%d/%s" % (self.host, self.port, self.portal_name)
def openUrl(self, url):
# Send Accept-Charset headers to activate the UnicodeConflictResolver
# (imitating firefox 3.5.9 here)
headers = { 'Accept-Charset' : 'ISO-8859-1,utf-8;q=0.7,*;q=0.7' }
request = urllib2.Request(url, headers=headers)
# Try to use long timeout, this is needed when there is many
# activities runing
try:
f = urllib2.urlopen(request, timeout=3600*4)
except TypeError:
f = urllib2.urlopen(request)
file_content = f.read()
f.close()
return file_content
def main(self):
self.setUp()
self.launchFuntionalTest()
def launchFuntionalTest(self):
status = self.getStatus()
xvfb_pid = None
firefox_pid = None
try:
if not self.debug:
xvfb_pid = self.runXvfb(self.xvfb_display)
firefox_pid = self.runFirefox(self.xvfb_display)
while True:
sleep(10)
cur_status = self.getStatus()
if status != cur_status:
break
finally:
if xvfb_pid:
os.kill(xvfb_pid, signal.SIGTERM)
if firefox_pid:
os.kill(firefox_pid, signal.SIGTERM)
def startZope(self):
os.environ['erp5_save_data_fs'] = "1"
os.system('%s/bin/zopectl start' % self.instance_home)
sleep(2) # ad hoc
def stopZope(self):
os.system('%s/bin/zopectl stop' % self.instance_home)
def runXvfb(self, xvfb_display):
pid = os.spawnlp(os.P_NOWAIT, 'Xvfb', 'Xvfb',
'-fbdir' , '%s' % self.xvfb_fbdir ,
':%s' % xvfb_display)
display = os.environ.get('DISPLAY')
if display:
auth = Popen(['xauth', 'list', display], stdout=PIPE).communicate()[0]
if auth:
(displayname, protocolname, hexkey) = auth.split()
Popen(['xauth', 'add', 'localhost/unix:%s' %xvfb_display, protocolname, hexkey])
print 'Xvfb : %d' % pid
print 'Take screenshots using xwud -in %s/Xvfb_screen0' % self.xvfb_fbdir
return pid
def getPrefJs(self, host, port):
prefs_js = """
// Don't ask if we want to switch default browsers
user_pref("browser.shell.checkDefaultBrowser", false);
// Disable pop-up blocking
user_pref("browser.allowpopups", true);
user_pref("dom.disable_open_during_load", false);
// Configure us as the local proxy
//user_pref("network.proxy.type", 2);
// Disable security warnings
user_pref("security.warn_submit_insecure", false);
user_pref("security.warn_submit_insecure.show_once", false);
user_pref("security.warn_entering_secure", false);
user_pref("security.warn_entering_secure.show_once", false);
user_pref("security.warn_entering_weak", false);
user_pref("security.warn_entering_weak.show_once", false);
user_pref("security.warn_leaving_secure", false);
user_pref("security.warn_leaving_secure.show_once", false);
user_pref("security.warn_viewing_mixed", false);
user_pref("security.warn_viewing_mixed.show_once", false);
// Disable "do you want to remember this password?"
user_pref("signon.rememberSignons", false);
// increase the timeout before warning of unresponsive script
user_pref("dom.max_script_run_time", 120);
// this is required to upload files
user_pref("capability.principal.codebase.p1.granted", "UniversalFileRead");
user_pref("signed.applets.codebase_principal_support", true);
user_pref("capability.principal.codebase.p1.id", "http://%s");
user_pref("capability.principal.codebase.p1.subjectName", "");""" % \
'%s:%s' % (host, port)
return prefs_js
def prepareFirefox(self, prefs_js=''):
os.system("rm -rf %s" % self.profile_dir)
os.mkdir(self.profile_dir)
pref_file = open(os.path.join(self.profile_dir, 'prefs.js'), 'w')
pref_file.write(prefs_js)
pref_file.close()
def runFirefox(self,xvfb_display):
prefs_js = self.getPrefJs(self.host, self.port)
self.prepareFirefox(prefs_js)
if self.debug:
try:
shutil.copy2(os.path.expanduser('~/.Xauthority'), '%s/.Xauthority' % self.profile_dir)
except IOError:
pass
else:
os.environ['DISPLAY'] = ':%s' %xvfb_display
os.environ['MOZ_NO_REMOTE'] = '1'
os.environ['HOME'] = self.profile_dir
os.environ['LC_ALL'] = 'C'
# check if old zelenium or new zelenium
try:
urllib2.urlopen("%s/portal_tests/core/scripts/selenium-version.js" % self.portal_url)
except urllib2.HTTPError:
# Zelenium 0.8
url_string = "%s/portal_tests/?auto=true&__ac_name=%s&__ac_password=%s" % (self.portal_url, self.user, self.password)
else:
# Zelenium 0.8+ or later
url_string = "%s/portal_tests/core/TestRunner.html?test=../test_suite_html&auto=on&resultsUrl=%s/portal_tests/postResults&__ac_name=%s&__ac_password=%s" % (self.portal_url, self.portal_url, self.user, self.password)
if self.run_only:
url_string = url_string.replace('/portal_tests/', '/portal_tests/%s/' % self.run_only, 1)
pid = os.spawnlp(os.P_NOWAIT, "firefox", "firefox",
"-no-remote", "-profile", self.profile_dir,
url_string)
os.environ['MOZ_NO_REMOTE'] = '0'
print 'firefox : %d' % pid
return pid
def getStatus(self):
try:
status = self.openUrl('%s/portal_tests/TestTool_getResults'
% (self.portal_url))
except urllib2.HTTPError, e:
if e.msg == "No Content" :
status = ""
else:
raise
return status
def setPreference(self):
conversion_server_url = os.environ.get('conversion_server_url', '')
conversion_server_hostname = os.environ.get('conversion_server_hostname',
'localhost')
conversion_server_port = os.environ.get('conversion_server_port', '8008')
urllib2.urlopen('%s/Zuite_setPreference?__ac_name='
'%s&__ac_password=%s&working_copy_list=%s'
'&conversion_server_url=%s'%
(self.portal_url, self.user, self.password,
bt5_dir_list, conversion_server_url,))
def unsubscribeFromTimerService(self):
urllib2.urlopen('%s/portal_activities/?unsubscribe:method='
'&__ac_name=%s&__ac_password=%s' %
(self.portal_url, self.user, self.password))
def setUp(self):
self.setPreference()
self.unsubscribeFromTimerService()
def getSvnRevision(self):
"""Get svn revision used."""
import pysvn
return pysvn.Client().info(os.path.dirname(__file__)).revision.number
def sendResult(self):
file_content = self.openUrl('%s/portal_tests/TestTool_getResults' % self.portal_url)
passes_re = re.compile('<th[^>]*>Tests passed</th>\n\s*<td[^>]*>([^<]*)')
failures_re = re.compile('<th[^>]*>Tests failed</th>\n\s*<td[^>]*>([^<]*)')
image_re = re.compile('<img[^>]*?>')
error_title_re = re.compile('(?:error.gif.*?>|title status_failed"><td[^>]*>)([^>]*?)</td></tr>', re.S)
result_re = re.compile('<div style="padding-top: 10px;">\s*<p>\s*'
'<img.*?</div>\s.*?</div>\s*', re.S)
error_result_re = re.compile('.*(?:error.gif|title status_failed).*', re.S)
passes = passes_re.search(file_content).group(1)
failures = failures_re.search(file_content).group(1)
error_titles = [re.compile('\s+').sub(' ', x).strip()
for x in error_title_re.findall(file_content)]
revision = self.getSvnRevision()
subject = "%s r%s: Functional Tests, %s Passes, %s Failures" \
% (self.email_subject, revision, passes, failures)
summary = """
Test Summary
Tests passed: %4s
Tests failed: %4s
Following tests failed:
%s""" % (passes, failures, "\n".join(error_titles))
detail = ''
for e in result_re.findall(file_content):
if error_result_re.match(e):
detail += e
detail = image_re.sub('', detail)
if detail:
detail = '''<html>
<head>
<style type="text/css">tr.status_failed { background-color:red };</style>
</head>
<body>%s</body>
</html>''' % detail
status = (not failures)
if self.send_mail:
sendMail(subject=subject,
body=summary,
status=status,
attachments=[detail],
from_mail='nobody@svn.erp5.org',
to_mail=[self.email_to_address],
smtp_host=self.smtp_host)
if self.stdout:
print '-' * 79
print subject
print '-' * 79
print summary
print '-' * 79
print detail
return int(failures)
if __name__ == "__main__":
test_runner = FunctionalTestRunner(instance_home)
test_runner.parseArgs()
test_runner.startZope()
atexit.register(test_runner.stopZope)
test_runner.main()
sys.exit(test_runner.sendResult())
##############################################################################
#
# Copyright (c) 2007 Nexedi SARL and Contributors. All Rights Reserved.
# Kazuhiko <kazuhiko@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
"""Send a mail with attachments.
"""
import smtplib
import re
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.message import Message
def sendMail(subject,
body,
attachments = [],
status = False,
from_mail = 'nobody@erp5.org',
to_mail = [ 'erp5-report@erp5.org' ],
smtp_host = ''):
if attachments:
msg = MIMEMultipart()
else:
msg = Message()
msg['Subject'] = subject
msg['From'] = from_mail
msg['To'] = ', '.join(to_mail)
msg['X-ERP5-Tests'] = 'ERP5'
if status:
msg['X-ERP5-Tests-Status'] = 'OK'
# Guarantees the message ends in a newline
msg.preamble = subject
msg.epilogue = ''
if attachments:
mime_text = MIMEText(body)
mime_text.add_header('Content-Disposition', 'attachment',
filename='body')
msg.attach(mime_text)
html_re = re.compile('<html>', re.I)
for item in attachments:
mime_text = MIMEText(item)
if html_re.match(item):
mime_text.set_type('text/html')
mime_text.add_header('Content-Disposition', 'attachment',
filename='attachment.html')
else:
mime_text.add_header('Content-Disposition', 'attachment',
filename='attachment.txt')
msg.attach(mime_text)
else:
msg.set_payload(body)
# Send the email via SMTP server.
if smtp_host:
s = smtplib.SMTP(smtp_host)
else:
s = smtplib.SMTP()
s.connect()
s.sendmail(from_mail, to_mail, msg.as_string())
s.close()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment