| Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 1 | # -*- coding: utf-8 -*- |
| 2 | """ |
| 3 | conftest |
| 4 | ~~~~~~~~ |
| 5 | |
| 6 | Configure py.test for support stuff. |
| 7 | |
| 8 | :copyright: 2007 by Armin Ronacher, Alexander Schremmer. |
| 9 | :license: BSD, see LICENSE for more details. |
| 10 | """ |
| 11 | |
| 12 | import os |
| 13 | import sys |
| 14 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) |
| 15 | |
| 16 | import py |
| Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 17 | from jinja import Environment |
| Armin Ronacher | c1e3040 | 2007-03-18 22:41:09 +0100 | [diff] [blame] | 18 | from jinja.parser import Parser |
| Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 19 | |
| Armin Ronacher | ccf284b | 2007-05-21 16:44:26 +0200 | [diff] [blame] | 20 | try: |
| 21 | # This code adds support for coverage.py (see |
| 22 | # http://nedbatchelder.com/code/modules/coverage.html). |
| 23 | # It prints a coverage report for the modules specified in all |
| 24 | # module globals (of the test modules) named "coverage_modules". |
| 25 | |
| 26 | import coverage, atexit |
| 27 | |
| 28 | IGNORED_MODULES = ['jinja._speedups', 'jinja.defaults', |
| 29 | 'jinja.translators'] |
| 30 | |
| 31 | def report_coverage(): |
| 32 | coverage.stop() |
| 33 | module_list = [ |
| 34 | mod for name, mod in sys.modules.copy().iteritems() if |
| 35 | getattr(mod, '__file__', None) and |
| 36 | name.startswith('jinja.') and |
| 37 | name not in IGNORED_MODULES |
| 38 | ] |
| 39 | module_list.sort() |
| 40 | coverage.report(module_list) |
| 41 | |
| 42 | def callback(option, opt_str, value, parser): |
| 43 | atexit.register(report_coverage) |
| 44 | coverage.erase() |
| 45 | coverage.start() |
| 46 | |
| 47 | py.test.config.addoptions('Test options', py.test.config.Option('-C', |
| 48 | '--coverage', action='callback', callback=callback, |
| 49 | help='Output information about code coverage (slow!)')) |
| 50 | |
| 51 | except ImportError: |
| 52 | coverage = None |
| 53 | |
| Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 54 | |
| Armin Ronacher | c1e3040 | 2007-03-18 22:41:09 +0100 | [diff] [blame] | 55 | class GlobalLoader(object): |
| 56 | |
| 57 | def __init__(self, scope): |
| 58 | self.scope = scope |
| 59 | |
| 60 | def get_source(self, environment, name, parent, scope=None): |
| 61 | return self.scope[name.upper() + 'TEMPLATE'] |
| 62 | |
| 63 | def parse(self, environment, name, parent, scope=None): |
| 64 | return Parser(environment, self.get_source(environment, name, |
| 65 | parent, scope), name).parse() |
| 66 | |
| 67 | def load(self, environment, name, translator, scope=None): |
| 68 | return translator.process(environment, self.parse(environment, |
| 69 | name, None, scope)) |
| 70 | |
| 71 | |
| 72 | loader = GlobalLoader(globals()) |
| Armin Ronacher | ee2c18e | 2007-04-20 22:39:04 +0200 | [diff] [blame] | 73 | simple_env = Environment(trim_blocks=True, friendly_traceback=False, loader=loader) |
| Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 74 | |
| 75 | |
| Armin Ronacher | 143a07e | 2007-06-02 01:47:34 +0200 | [diff] [blame^] | 76 | class MemcacheClient(object): |
| 77 | """ |
| 78 | Helper for the loader test. |
| 79 | """ |
| 80 | |
| 81 | def __init__(self, hosts): |
| 82 | self.cache = {} |
| 83 | |
| 84 | def get(self, name): |
| 85 | return self.cache.get(name) |
| 86 | |
| 87 | def set(self, name, data, time): |
| 88 | self.cache[name] = data |
| 89 | |
| 90 | sys.modules['memcache'] = memcache = type(sys)('memcache') |
| 91 | memcache.Client = MemcacheClient |
| 92 | |
| 93 | |
| Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 94 | class Module(py.test.collect.Module): |
| 95 | |
| 96 | def __init__(self, *args, **kwargs): |
| 97 | self.env = simple_env |
| 98 | super(Module, self).__init__(*args, **kwargs) |
| 99 | |
| Armin Ronacher | ccf284b | 2007-05-21 16:44:26 +0200 | [diff] [blame] | 100 | def makeitem(self, name, obj, usefilters=True): |
| 101 | if name.startswith('test_'): |
| 102 | if hasattr(obj, 'func_code'): |
| 103 | return JinjaTestFunction(name, parent=self) |
| 104 | elif isinstance(obj, basestring): |
| 105 | return JinjaDocTest(name, parent=self) |
| Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 106 | |
| 107 | |
| 108 | class JinjaTestFunction(py.test.collect.Function): |
| 109 | |
| 110 | def execute(self, target, *args): |
| Armin Ronacher | c1e3040 | 2007-03-18 22:41:09 +0100 | [diff] [blame] | 111 | loader.scope = target.func_globals |
| Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 112 | co = target.func_code |
| 113 | if 'env' in co.co_varnames[:co.co_argcount]: |
| 114 | target(self.parent.env, *args) |
| 115 | else: |
| 116 | target(*args) |
| Armin Ronacher | ccf284b | 2007-05-21 16:44:26 +0200 | [diff] [blame] | 117 | |
| 118 | |
| 119 | class JinjaDocTest(py.test.collect.Item): |
| 120 | |
| 121 | def run(self): |
| 122 | mod = py.std.types.ModuleType(self.name) |
| 123 | mod.__doc__ = self.obj |
| 124 | self.execute(mod) |
| 125 | |
| 126 | def execute(self, mod): |
| 127 | mod.env = self.parent.env |
| 128 | mod.MODULE = self.parent.obj |
| 129 | failed, tot = py.compat.doctest.testmod(mod, verbose=True) |
| 130 | if failed: |
| 131 | py.test.fail('doctest %s: %s failed out of %s' % ( |
| 132 | self.fspath, failed, tot)) |