Skip to content

Commit c74bbd1

Browse files
committed
simplified and cleaned-up system for running acceptance tests
1 parent 50804da commit c74bbd1

3 files changed

Lines changed: 140 additions & 105 deletions

File tree

test/libs/examplelib.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
import sys
2+
3+
14
class AcceptanceTestLibrary:
25
_unicode = (u'Hyv\u00E4\u00E4 y\u00F6t\u00E4. '
36
u'\u0421\u043F\u0430\u0441\u0438\u0431\u043E!')
47

8+
def get_server_language(self):
9+
return 'Jython' if sys.platform.startswith('java') else 'Python'
10+
511
# Basic communication (and documenting keywords)
612

713
def passing(self):
@@ -295,7 +301,6 @@ class MyException(Exception):
295301

296302

297303
if __name__ == '__main__':
298-
import sys
299304
from robotremoteserver import RobotRemoteServer
300305

301306
RobotRemoteServer(AcceptanceTestLibrary(), *sys.argv[1:])

test/run.py

Lines changed: 50 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,58 @@
11
#!/usr/bin/env python
2-
"""Script for running the remote library tests against different servers.
32

4-
Usage 1: run.py language[:runner] [[options] datasources]
3+
"""Script for running the remote server tests using different interpreters.
54
6-
Valid languages are 'python', 'jython' or 'ruby', and runner can
7-
either by 'pybot' (default) or 'jybot'. By default, all tests under
8-
'test/data' directory are run, but this can be changed by providing
9-
options, which can be any Robot Framework command line options.
5+
usage: run.py server[:runner] [[options] datasources]
106
11-
Usage 2: run.py stop [port]
7+
`server` is the only required argument and specifies the server interpreter
8+
to use. `runner` is the interpreter to use for running tests, defaulting to
9+
the server interpreter.
1210
13-
Stops remote server in specified port. Default port is 8270.
11+
By default all tests under `tests` directory are executed. This can be
12+
changed by giving data sources and options explicitly.
1413
"""
14+
1515
import sys
16-
import xmlrpclib
17-
import time
18-
import os
1916
import subprocess
20-
import shutil
21-
import socket
22-
23-
REMOTEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
24-
OUTPUTDIR = os.path.join(REMOTEDIR, 'test', 'logs')
25-
if os.path.exists(OUTPUTDIR):
26-
shutil.rmtree(OUTPUTDIR)
27-
os.mkdir(OUTPUTDIR)
28-
29-
30-
class Library:
31-
32-
def __init__(self, language=None):
33-
if language:
34-
self._start_library(language)
35-
if not self.test(attempts=15):
36-
raise RuntimeError("Starting %s library failed" % language)
37-
38-
def _start_library(self, lang):
39-
opts = self._environment_setup(lang)
40-
ext = {'python': 'py', 'jython': 'py', 'ruby': 'rb'}[lang]
41-
lib = os.path.join(REMOTEDIR, 'test', 'libs', 'examplelib.%s' % ext)
42-
stdout = os.path.join(OUTPUTDIR, 'stdout.txt')
43-
stderr = os.path.join(OUTPUTDIR, 'stderr.txt')
44-
cmd = '%s%s%s 1> %s 2> %s' % (lang, opts, lib, stdout, stderr)
45-
print 'Starting %s remote library with command:\n%s' % (lang, cmd)
46-
subprocess.Popen(cmd, shell=True)
47-
48-
def _environment_setup(self, lang):
49-
if lang == 'jython':
50-
return ' -Dpython.path=%s ' % os.path.join(REMOTEDIR, 'src')
51-
varname = {'python': 'PYTHONPATH', 'ruby': 'LOAD_PATH'}[lang]
52-
os.environ[varname] = os.path.join(REMOTEDIR, 'src')
53-
print '%s: %s' % (varname, REMOTEDIR)
54-
return ' '
55-
56-
def test(self, port=8270, attempts=1):
57-
url = 'http://localhost:%s' % port
58-
for i in range(attempts):
59-
try:
60-
xmlrpclib.ServerProxy(url).get_keyword_names()
61-
except socket.error, (errno, errmsg):
62-
time.sleep(1)
63-
except xmlrpclib.Error, err:
64-
errmsg = err.faultString
65-
break
66-
else:
67-
print "Remote library is running on port %s" % port
68-
return True
69-
print "Failed to connect to library on port %s: %s" % (port, errmsg)
70-
return False
71-
72-
def stop(self, port=8270):
73-
if self.test(port):
74-
server = xmlrpclib.ServerProxy('http://localhost:%s' % port)
75-
server.stop_remote_server()
76-
print "Remote library on port %s stopped" % port
77-
78-
79-
if __name__ == '__main__':
80-
if len(sys.argv) < 2:
81-
print __doc__
82-
sys.exit(1)
83-
mode = sys.argv[1]
84-
if mode == 'stop':
85-
Library().stop(*sys.argv[2:])
86-
sys.exit()
87-
88-
if ':' in mode:
89-
lang, runner = mode.split(':')
90-
else:
91-
lang, runner = mode, 'pybot'
92-
lib = Library(lang)
93-
include = lang if lang != 'jython' else 'python'
94-
output = os.path.join(OUTPUTDIR, 'output.xml')
95-
args = [runner, '--log', 'NONE', '--report', 'NONE', '--output', output,
96-
'--name', mode, '--include', include, '--noncritical', 'non-critical']
97-
if len(sys.argv) == 2:
98-
args.append(os.path.join(REMOTEDIR, 'test', 'atest'))
99-
else:
100-
args.extend(sys.argv[2:])
101-
print 'Running tests with command:\n%s' % ' '.join(args)
102-
subprocess.call(args)
103-
lib.stop()
104-
print
105-
checker = os.path.join(REMOTEDIR, 'test', 'statuschecker.py')
106-
subprocess.call(['python', checker, output])
107-
rc = subprocess.call(['rebot', '--noncritical', 'non-critical',
108-
'--outputdir', OUTPUTDIR, output])
109-
if rc == 0:
110-
print 'All tests passed'
111-
else:
112-
print '%d test%s failed' % (rc, 's' if rc != 1 else '')
17+
from os.path import abspath, dirname, exists, join
18+
from os import mkdir
19+
from shutil import rmtree
20+
21+
import robot
22+
23+
import servercontroller
24+
import statuschecker
25+
26+
ROOT = dirname(abspath(__file__))
27+
RESULTS = join(ROOT, 'results')
28+
OUTPUT = join(RESULTS, 'output.xml')
29+
if exists(RESULTS):
30+
rmtree(RESULTS)
31+
mkdir(RESULTS)
32+
33+
34+
if len(sys.argv) == 1 or '-h' in sys.argv or '--help' in sys.argv:
35+
sys.exit(__doc__)
36+
37+
interpreters = sys.argv[1]
38+
if ':' in interpreters:
39+
server_interpreter, runner_interpreter = interpreters.rsplit(':', 1)
40+
else:
41+
server_interpreter = runner_interpreter = interpreters
42+
43+
servercontroller.start(server_interpreter)
44+
45+
args = [runner_interpreter, '-m', 'robot.run', '--name', interpreters,
46+
'--output', OUTPUT, '--log', 'NONE', '--report', 'NONE']
47+
args.extend(sys.argv[2:] or [join(ROOT, 'tests')])
48+
print 'Running tests with command:\n%s' % ' '.join(args)
49+
subprocess.call(args)
50+
51+
servercontroller.stop()
52+
print
53+
statuschecker.process_output(OUTPUT)
54+
rc = robot.rebot(OUTPUT, outputdir=RESULTS)
55+
if rc == 0:
56+
print 'All tests passed'
57+
else:
58+
print '%d test%s failed' % (rc, 's' if rc != 1 else '')

test/servercontroller.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!/usr/bin/env python
2+
3+
"""Module/script for controlling remote server used in tests.
4+
5+
When used as module, provides `start`, `test`, and `stop` methods.
6+
7+
Command line usage:
8+
servercontroller.py start [interpreter=sys.executable]
9+
servercontroller.py test [port=8270] [attempts=1]
10+
servercontroller.py stop [port=8270]
11+
12+
Note: Starting from CLI leaves the terminal into messed up state.
13+
"""
14+
15+
from __future__ import with_statement
16+
import xmlrpclib
17+
import time
18+
import subprocess
19+
import socket
20+
from os.path import abspath, dirname, exists, join
21+
import os
22+
import sys
23+
24+
25+
BASE = dirname(abspath(__file__))
26+
27+
28+
def start(interpreter=sys.executable, library='examplelib.py'):
29+
results = _get_result_directory()
30+
with open(join(results, 'server.txt'), 'w') as output:
31+
subprocess.Popen([interpreter, join(BASE, 'libs', library)],
32+
stdout=output, stderr=subprocess.STDOUT,
33+
env=_get_environ())
34+
if not test(attempts=10):
35+
raise RuntimeError('Starting remote server failed')
36+
37+
def _get_result_directory():
38+
path = join(BASE, 'results')
39+
if not exists(path):
40+
os.mkdir(path)
41+
return path
42+
43+
def _get_environ():
44+
environ = os.environ.copy()
45+
src = join(BASE, '..', 'src')
46+
environ.update(PYTHONPATH=src, JYTHONPATH=src, IRONPYTHONPATH=src)
47+
return environ
48+
49+
50+
def test(port=8270, attempts=1):
51+
url = 'http://localhost:%s' % port
52+
for i in range(int(attempts)):
53+
if i > 0:
54+
time.sleep(1)
55+
try:
56+
ret = xmlrpclib.ServerProxy(url).run_keyword('get_server_language', [])
57+
except socket.error, (errno, errmsg):
58+
pass
59+
except xmlrpclib.Error, err:
60+
errmsg = err.faultString
61+
break
62+
else:
63+
print "%s remote server running on port %s" % (ret['return'], port)
64+
return True
65+
print "Failed to connect to remote server on port %s: %s" % (port, errmsg)
66+
return False
67+
68+
69+
def stop(port=8270):
70+
if test(port):
71+
server = xmlrpclib.ServerProxy('http://localhost:%s' % port)
72+
server.stop_remote_server()
73+
print "Remote server on port %s stopped" % port
74+
75+
76+
if __name__ == '__main__':
77+
if len(sys.argv) == 1 or '-h' in sys.argv or '--help' in sys.argv:
78+
sys.exit(__doc__)
79+
mode = sys.argv[1]
80+
args = sys.argv[2:]
81+
try:
82+
{'start': start, 'stop': stop, 'test': test}[mode](*args)
83+
except (KeyError, TypeError):
84+
sys.exit(__doc__)

0 commit comments

Comments
 (0)