Skip to content

Commit 169908f

Browse files
author
Jordan Baker
committed
initial version
0 parents  commit 169908f

15 files changed

+309
-0
lines changed

roadrunner.egg-info/PKG-INFO

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Metadata-Version: 1.0
2+
Name: roadrunner
3+
Version: 0.1dev
4+
Summary: UNKNOWN
5+
Home-page: UNKNOWN
6+
Author: Jordan Baker
7+
Author-email: [email protected]
8+
License: ZPL
9+
Description: UNKNOWN
10+
Platform: UNKNOWN

roadrunner.egg-info/SOURCES.txt

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
setup.cfg
2+
setup.py
3+
roadrunner/__init__.py
4+
roadrunner/runner.py
5+
roadrunner.egg-info/PKG-INFO
6+
roadrunner.egg-info/SOURCES.txt
7+
roadrunner.egg-info/dependency_links.txt
8+
roadrunner.egg-info/entry_points.txt
9+
roadrunner.egg-info/not-zip-safe
10+
roadrunner.egg-info/paster_plugins.txt
11+
roadrunner.egg-info/top_level.txt
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

roadrunner.egg-info/entry_points.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
[console_scripts]
3+
roadrunner = roadrunner.runner:main
4+

roadrunner.egg-info/not-zip-safe

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PasteScript

roadrunner.egg-info/top_level.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
roadrunner

roadrunner/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#

roadrunner/__init__.pyc

157 Bytes
Binary file not shown.

roadrunner/runner.py

+229
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
"""
2+
roadrunner (or rr)
3+
4+
aka. looping testrunner with environment preloading for test-driven development
5+
6+
preloads a standard Zope & Plone test environment compatible with
7+
PloneTestCase.
8+
9+
Tests are then run in a loop. You are given a shell-like environment with
10+
command history where you can select different tests, etc.
11+
12+
Limitiations
13+
============
14+
15+
Because it preloads the Plone environment you won't be able to see changes
16+
to the Core Plone components. However, it should see all changes in your
17+
application code which is what you will most likely be changing anyways.
18+
Unless you are a core developer.
19+
20+
Theoretically this should be able to work with any test environment (eg.
21+
Django, TG, Twisted).
22+
23+
I eventually plan to do this, and would accept any patches in the meantime
24+
if anyone feels so inclined.
25+
26+
Author
27+
======
28+
29+
Jordan Baker <[email protected]>
30+
31+
TODO
32+
====
33+
34+
- ability to preload any arbitrary layers, plus some presets like --plone or --grok
35+
- hooks for fixture configuration?
36+
- tests... how ironic this code has none, but it started as a proof of concept
37+
"""
38+
from zope.testing import testrunner
39+
import os, sys, time
40+
import shlex
41+
42+
try:
43+
import readline
44+
HAVE_READLINE=True
45+
except:
46+
HAVE_READLINE=False
47+
48+
def run_commandloop(args):
49+
while 1:
50+
cmdline = raw_input("rr> ").strip()
51+
if cmdline:
52+
cmdargs = shlex.split(cmdline)
53+
if cmdargs[0] in ('quit', 'exit'):
54+
sys.exit(0)
55+
if cmdargs[0] in ('help', '?'):
56+
print HELP_MESSAGE
57+
continue
58+
if cmdargs[0] == 'test':
59+
# ok we have some cmdline arguments
60+
args = cmdargs[1:]
61+
break
62+
else:
63+
print "Unknown command. Type 'help' for help."
64+
else:
65+
print "rr> test " + shlex_join(args)
66+
break
67+
return args
68+
69+
def main(zope_conf, args=sys.argv):
70+
sys.argv = ['fakepath'] # Zope configure whines about argv stuff make it shutup
71+
bootstrap_zope(zope_conf)
72+
args = args[2:]
73+
if HAVE_READLINE:
74+
readline.add_history('test ' + shlex_join(args))
75+
76+
## preload test environment
77+
t1 = time.time()
78+
setup_layers = preload_plone()
79+
t2 = time.time()
80+
preload_time = t2-t1
81+
print 'Preloading took: %0.3f seconds.' % (preload_time)
82+
83+
defaults = testrunner_defaults()
84+
defaults = setup_paths(defaults)
85+
86+
saved_time = 0
87+
while 1:
88+
# Test Loop Start
89+
pid = os.fork()
90+
if not pid:
91+
# Run tests in child process
92+
t1 = time.time()
93+
rc = testrunner.run(defaults=defaults, args=args,
94+
setup_layers=setup_layers)
95+
t2 = time.time()
96+
print 'Testrunner took: %0.3f seconds. ' % ((t2-t1))
97+
sys.exit(rc)
98+
99+
else:
100+
# In parent process
101+
try:
102+
status = os.wait()
103+
# print "\nchild process returned: ", repr(status)
104+
except OSError:
105+
print "\nchild process was interrupted!"
106+
107+
args = run_commandloop(args)
108+
109+
# add to saved_time
110+
# start the test loop over....
111+
112+
def bootstrap_zope(config_file):
113+
config_file = os.path.abspath(config_file)
114+
print "Parsing %s" % config_file
115+
import Zope2
116+
Zope2.configure(config_file)
117+
118+
def filter_warnings():
119+
import warnings
120+
warnings.simplefilter('ignore', Warning, append=True)
121+
filter_warnings()
122+
123+
def maybe_quote_args(arg):
124+
if ' ' in arg:
125+
return '"' + arg + '"'
126+
else:
127+
return arg
128+
129+
def shlex_join(args, char=' '):
130+
l = map(maybe_quote_args, args)
131+
return char.join(args)
132+
133+
HELP_MESSAGE = \
134+
"""\
135+
roadrunner help
136+
--------------
137+
138+
exit
139+
to quit
140+
141+
test <testrunner arguments>
142+
run the testrunner
143+
144+
help
145+
this message
146+
147+
Press the <return> key to run the test again with the same arguments.
148+
149+
If you have readline you can use that to search your history.
150+
"""
151+
152+
def setup_paths(defaults):
153+
"""
154+
this code is from Zope's test.py
155+
"""
156+
# Put all packages found in products directories on the test-path.
157+
import Products
158+
products = []
159+
softwarehome = '/Users/jbb/co/shared_plone3/parts/zope2/lib/python'
160+
161+
for path in Products.__path__:
162+
# ignore software home, as it already works
163+
if not path.startswith(softwarehome):
164+
# get all folders in the current products folder and filter
165+
# out everything that is not a directory or a VCS internal one.
166+
folders = [f for f in os.listdir(path) if
167+
os.path.isdir(os.path.join(path, f)) and
168+
not f.startswith('.') and not f == 'CVS']
169+
if folders:
170+
for folder in folders:
171+
# look into all folders and see if they have an
172+
# __init__.py in them. This filters out non-packages
173+
# like for example documenation folders
174+
package = os.path.join(path, folder)
175+
if os.path.exists(os.path.join(package, '__init__.py')):
176+
products.append(package)
177+
178+
# Put all packages onto the search path as a package. As we only deal
179+
# with products, the package name is always prepended by 'Products.'
180+
for product in products:
181+
defaults += ['--package-path', product, 'Products.%s' % os.path.split(product)[-1]]
182+
183+
paths = sys.path
184+
# progname = self.options.progname
185+
buildout_root = '/Users/jordan/co/myplatform_buildout/trunk' #os.path.dirname(os.path.dirname(progname))
186+
187+
for path in paths:
188+
if path != buildout_root:
189+
defaults += ['--test-path', path]
190+
191+
return defaults
192+
193+
def preload_plone():
194+
print "Preloading Plone ..."
195+
from Products.PloneTestCase.layer import PloneSite
196+
from Products.PloneTestCase import PloneTestCase as ptc
197+
ptc.setupPloneSite()
198+
# pre-setup Plone layer
199+
from zope.testing.testrunner import setup_layer
200+
setup_layers={}
201+
setup_layer(PloneSite, setup_layers)
202+
# delete the plone layer registration so that the testrunner
203+
# will re-run Plone layer setUp after deferred setups have
204+
# been registered by the associated tests.
205+
del setup_layers[PloneSite]
206+
return setup_layers
207+
208+
def testrunner_defaults():
209+
defaults = '--tests-pattern ^tests$ -v'.split()
210+
211+
return defaults
212+
213+
def register_signal_handlers(pid):
214+
# propogate signals to child process
215+
import signal
216+
#
217+
# def interrupt_handler(signum, frame, pid=pid):
218+
# try:
219+
# print "received interrupt, killing pid %s" % pid
220+
# os.kill(pid, signal.SIGKILL)
221+
# except OSError, e:
222+
# print e, pid
223+
#
224+
# signal.signal(signal.SIGINT, interrupt_handler)
225+
# # restore signal handler
226+
# signal.signal(signal.SIGINT, signal.SIG_DFL)
227+
228+
if __name__ == '__main__':
229+
main()

roadrunner/runner.pyc

6.01 KB
Binary file not shown.

roadrunner/tests.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""
2+
"""
3+
4+
import unittest
5+
6+
7+
class TestRoadrunner(unittest.TestCase):
8+
def setUp(self):
9+
pass
10+
def test_stub(self):
11+
assert 1 == 1
12+
13+
def test_suite():
14+
from unittest import TestSuite, makeSuite
15+
suite = TestSuite()
16+
suite.addTest(makeSuite(TestRoadrunner))
17+
return suite
18+
19+
if __name__ == '__main__':
20+
unittest.main()

roadrunner/tests.pyc

952 Bytes
Binary file not shown.

setup.cfg

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[egg_info]
2+
tag_build = dev
3+
tag_svn_revision = true

setup.py

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from setuptools import setup, find_packages
2+
import sys, os
3+
4+
version = '0.1'
5+
6+
setup(name='roadrunner',
7+
version=version,
8+
description="",
9+
long_description="""\
10+
""",
11+
classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
12+
keywords='',
13+
author='Jordan Baker',
14+
author_email='[email protected]',
15+
url='',
16+
license='ZPL',
17+
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
18+
include_package_data=True,
19+
zip_safe=False,
20+
install_requires=[
21+
# -*- Extra requirements: -*-
22+
],
23+
entry_points = """
24+
[console_scripts]
25+
roadrunner = roadrunner.runner:main
26+
"""
27+
)

0 commit comments

Comments
 (0)