Show More
@@ -32,62 +32,33 from IPython.utils.sysinfo import sys_info | |||||
32 | from IPython.utils.tempdir import TemporaryDirectory |
|
32 | from IPython.utils.tempdir import TemporaryDirectory | |
33 |
|
33 | |||
34 |
|
34 | |||
35 |
class |
|
35 | class TestController(object): | |
36 |
"""Run |
|
36 | """Run tests in a subprocess | |
37 | """ |
|
37 | """ | |
38 | #: str, IPython test suite to be executed. |
|
38 | #: str, IPython test suite to be executed. | |
39 | section = None |
|
39 | section = None | |
40 | #: list, command line arguments to be executed |
|
40 | #: list, command line arguments to be executed | |
41 | cmd = None |
|
41 | cmd = None | |
42 | #: str, Python command to execute in subprocess |
|
|||
43 | pycmd = None |
|
|||
44 | #: dict, extra environment variables to set for the subprocess |
|
42 | #: dict, extra environment variables to set for the subprocess | |
45 | env = None |
|
43 | env = None | |
46 | #: list, TemporaryDirectory instances to clear up when the process finishes |
|
44 | #: list, TemporaryDirectory instances to clear up when the process finishes | |
47 | dirs = None |
|
45 | dirs = None | |
48 | #: subprocess.Popen instance |
|
46 | #: subprocess.Popen instance | |
49 | process = None |
|
47 | process = None | |
|
48 | #: str, process stdout+stderr | |||
|
49 | stdout = None | |||
|
50 | #: bool, whether to capture process stdout & stderr | |||
50 | buffer_output = False |
|
51 | buffer_output = False | |
51 |
|
52 | |||
52 |
def __init__(self |
|
53 | def __init__(self): | |
53 | """Create new test runner.""" |
|
54 | self.cmd = [] | |
54 | self.section = section |
|
|||
55 | # pycmd is put into cmd[2] in IPTestController.launch() |
|
|||
56 | self.cmd = [sys.executable, '-c', None, section] |
|
|||
57 | self.pycmd = "from IPython.testing.iptest import run_iptest; run_iptest()" |
|
|||
58 | self.env = {} |
|
55 | self.env = {} | |
59 | self.dirs = [] |
|
56 | self.dirs = [] | |
60 | ipydir = TemporaryDirectory() |
|
|||
61 | self.dirs.append(ipydir) |
|
|||
62 | self.env['IPYTHONDIR'] = ipydir.name |
|
|||
63 | self.workingdir = workingdir = TemporaryDirectory() |
|
|||
64 | self.dirs.append(workingdir) |
|
|||
65 | self.env['IPTEST_WORKING_DIR'] = workingdir.name |
|
|||
66 | # This means we won't get odd effects from our own matplotlib config |
|
|||
67 | self.env['MPLCONFIGDIR'] = workingdir.name |
|
|||
68 |
|
57 | |||
69 | @property |
|
58 | @property | |
70 | def will_run(self): |
|
59 | def will_run(self): | |
71 | return test_sections[self.section].will_run |
|
60 | """Override in subclasses to check for dependencies.""" | |
72 |
|
61 | return False | ||
73 | def add_xunit(self): |
|
|||
74 | xunit_file = os.path.abspath(self.section + '.xunit.xml') |
|
|||
75 | self.cmd.extend(['--with-xunit', '--xunit-file', xunit_file]) |
|
|||
76 |
|
||||
77 | def add_coverage(self): |
|
|||
78 | coverage_rc = ("[run]\n" |
|
|||
79 | "data_file = {data_file}\n" |
|
|||
80 | "source =\n" |
|
|||
81 | " {source}\n" |
|
|||
82 | ).format(data_file=os.path.abspath('.coverage.'+self.section), |
|
|||
83 | source="\n ".join(test_sections[self.section].includes)) |
|
|||
84 |
|
||||
85 | config_file = os.path.join(self.workingdir.name, '.coveragerc') |
|
|||
86 | with open(config_file, 'w') as f: |
|
|||
87 | f.write(coverage_rc) |
|
|||
88 |
|
||||
89 | self.env['COVERAGE_PROCESS_START'] = config_file |
|
|||
90 | self.pycmd = "import coverage; coverage.process_startup(); " + self.pycmd |
|
|||
91 |
|
62 | |||
92 | def launch(self): |
|
63 | def launch(self): | |
93 | # print('*** ENV:', self.env) # dbg |
|
64 | # print('*** ENV:', self.env) # dbg | |
@@ -96,7 +67,6 class IPTestController(object): | |||||
96 | env.update(self.env) |
|
67 | env.update(self.env) | |
97 | output = subprocess.PIPE if self.buffer_output else None |
|
68 | output = subprocess.PIPE if self.buffer_output else None | |
98 | stdout = subprocess.STDOUT if self.buffer_output else None |
|
69 | stdout = subprocess.STDOUT if self.buffer_output else None | |
99 | self.cmd[2] = self.pycmd |
|
|||
100 | self.process = subprocess.Popen(self.cmd, stdout=output, |
|
70 | self.process = subprocess.Popen(self.cmd, stdout=output, | |
101 | stderr=stdout, env=env) |
|
71 | stderr=stdout, env=env) | |
102 |
|
72 | |||
@@ -136,14 +106,63 class IPTestController(object): | |||||
136 |
|
106 | |||
137 | __del__ = cleanup |
|
107 | __del__ = cleanup | |
138 |
|
108 | |||
139 | def prepare_test_controllers(inc_slow=False, xunit=False, coverage=False): |
|
109 | class PyTestController(TestController): | |
140 | """Returns an ordered list of IPTestController instances to be run.""" |
|
110 | """Run Python tests using IPython.testing.iptest""" | |
|
111 | #: str, Python command to execute in subprocess | |||
|
112 | pycmd = None | |||
|
113 | ||||
|
114 | def __init__(self, section): | |||
|
115 | """Create new test runner.""" | |||
|
116 | TestController.__init__(self) | |||
|
117 | self.section = section | |||
|
118 | # pycmd is put into cmd[2] in PyTestController.launch() | |||
|
119 | self.cmd = [sys.executable, '-c', None, section] | |||
|
120 | self.pycmd = "from IPython.testing.iptest import run_iptest; run_iptest()" | |||
|
121 | ipydir = TemporaryDirectory() | |||
|
122 | self.dirs.append(ipydir) | |||
|
123 | self.env['IPYTHONDIR'] = ipydir.name | |||
|
124 | self.workingdir = workingdir = TemporaryDirectory() | |||
|
125 | self.dirs.append(workingdir) | |||
|
126 | self.env['IPTEST_WORKING_DIR'] = workingdir.name | |||
|
127 | # This means we won't get odd effects from our own matplotlib config | |||
|
128 | self.env['MPLCONFIGDIR'] = workingdir.name | |||
|
129 | ||||
|
130 | @property | |||
|
131 | def will_run(self): | |||
|
132 | return test_sections[self.section].will_run | |||
|
133 | ||||
|
134 | def add_xunit(self): | |||
|
135 | xunit_file = os.path.abspath(self.section + '.xunit.xml') | |||
|
136 | self.cmd.extend(['--with-xunit', '--xunit-file', xunit_file]) | |||
|
137 | ||||
|
138 | def add_coverage(self): | |||
|
139 | coverage_rc = ("[run]\n" | |||
|
140 | "data_file = {data_file}\n" | |||
|
141 | "source =\n" | |||
|
142 | " {source}\n" | |||
|
143 | ).format(data_file=os.path.abspath('.coverage.'+self.section), | |||
|
144 | source="\n ".join(test_sections[self.section].includes)) | |||
|
145 | ||||
|
146 | config_file = os.path.join(self.workingdir.name, '.coveragerc') | |||
|
147 | with open(config_file, 'w') as f: | |||
|
148 | f.write(coverage_rc) | |||
|
149 | ||||
|
150 | self.env['COVERAGE_PROCESS_START'] = config_file | |||
|
151 | self.pycmd = "import coverage; coverage.process_startup(); " + self.pycmd | |||
|
152 | ||||
|
153 | def launch(self): | |||
|
154 | self.cmd[2] = self.pycmd | |||
|
155 | super(PyTestController, self).launch() | |||
|
156 | ||||
|
157 | ||||
|
158 | def prepare_py_test_controllers(inc_slow=False, xunit=False, coverage=False): | |||
|
159 | """Returns an ordered list of PyTestController instances to be run.""" | |||
141 | to_run, not_run = [], [] |
|
160 | to_run, not_run = [], [] | |
142 | if not inc_slow: |
|
161 | if not inc_slow: | |
143 | test_sections['parallel'].enabled = False |
|
162 | test_sections['parallel'].enabled = False | |
144 |
|
163 | |||
145 | for name in test_group_names: |
|
164 | for name in test_group_names: | |
146 |
controller = |
|
165 | controller = PyTestController(name) | |
147 | if xunit: |
|
166 | if xunit: | |
148 | controller.add_xunit() |
|
167 | controller.add_xunit() | |
149 | if coverage: |
|
168 | if coverage: | |
@@ -217,9 +236,9 def run_iptestall(inc_slow=False, jobs=1, xunit_out=False, coverage_out=False): | |||||
217 | are processors |
|
236 | are processors | |
218 | """ |
|
237 | """ | |
219 | if jobs != 1: |
|
238 | if jobs != 1: | |
220 |
|
|
239 | TestController.buffer_output = True | |
221 |
|
240 | |||
222 | to_run, not_run = prepare_test_controllers(inc_slow=inc_slow, xunit=xunit_out, |
|
241 | to_run, not_run = prepare_py_test_controllers(inc_slow=inc_slow, xunit=xunit_out, | |
223 | coverage=coverage_out) |
|
242 | coverage=coverage_out) | |
224 |
|
243 | |||
225 | def justify(ltext, rtext, width=70, fill='-'): |
|
244 | def justify(ltext, rtext, width=70, fill='-'): |
General Comments 0
You need to be logged in to leave comments.
Login now