From 64cbe9f0a9a970de240ac7f7ce2d7b1459e1c787 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Fri, 3 Oct 2014 20:11:55 -0300 Subject: [PATCH] Usando pytest (setup e testes antigos convertidos) --- pytest.ini | 2 + setup.py | 8 + .../diagnosticos/templatetags/smart_if.py | 671 +++++++----------- .../templatetags/test_smart_if.py | 166 +++++ sigi/settings/base.py | 2 + sigi/settings/test.py | 16 + 6 files changed, 453 insertions(+), 412 deletions(-) create mode 100644 pytest.ini create mode 100644 setup.py create mode 100644 sigi/apps/diagnosticos/templatetags/test_smart_if.py create mode 100644 sigi/settings/test.py diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..370e5a9 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +DJANGO_SETTINGS_MODULE=sigi.settings.test diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..2ca58d5 --- /dev/null +++ b/setup.py @@ -0,0 +1,8 @@ +# py.test precisa deste arquivo para que o projeto seja instalado no virtualenv com: +# "pip install -e ." +# vide http://pytest-django.readthedocs.org/en/latest/faq.html#i-see-an-error-saying-could-not-import-myproject-settings +# +from distutils.core import setup + + +setup(name='sigi', version='2.x') diff --git a/sigi/apps/diagnosticos/templatetags/smart_if.py b/sigi/apps/diagnosticos/templatetags/smart_if.py index 2c38a69..5a09cd3 100644 --- a/sigi/apps/diagnosticos/templatetags/smart_if.py +++ b/sigi/apps/diagnosticos/templatetags/smart_if.py @@ -1,412 +1,259 @@ -""" -A smarter {% if %} tag for django templates. - -While retaining current Django functionality, it also handles equality, -greater than and less than operators. Some common case examples:: - - {% if articles|length >= 5 %}...{% endif %} - {% if "ifnotequal tag" != "beautiful" %}...{% endif %} -""" -import unittest -from django import template - - -register = template.Library() - - -#============================================================================== -# Calculation objects -#============================================================================== - -class BaseCalc(object): - - def __init__(self, var1, var2=None, negate=False): - self.var1 = var1 - self.var2 = var2 - self.negate = negate - - def resolve(self, context): - try: - var1, var2 = self.resolve_vars(context) - outcome = self.calculate(var1, var2) - except: - outcome = False - if self.negate: - return not outcome - return outcome - - def resolve_vars(self, context): - var2 = self.var2 and self.var2.resolve(context) - return self.var1.resolve(context), var2 - - def calculate(self, var1, var2): - raise NotImplementedError() - - -class Or(BaseCalc): - - def calculate(self, var1, var2): - return var1 or var2 - - -class And(BaseCalc): - - def calculate(self, var1, var2): - return var1 and var2 - - -class Equals(BaseCalc): - - def calculate(self, var1, var2): - return var1 == var2 - - -class Greater(BaseCalc): - - def calculate(self, var1, var2): - return var1 > var2 - - -class GreaterOrEqual(BaseCalc): - - def calculate(self, var1, var2): - return var1 >= var2 - - -class In(BaseCalc): - - def calculate(self, var1, var2): - return var1 in var2 - - -#============================================================================== -# Tests -#============================================================================== - -class TestVar(object): - - """ - A basic self-resolvable object similar to a Django template variable. Used - to assist with tests. - """ - - def __init__(self, value): - self.value = value - - def resolve(self, context): - return self.value - - -class SmartIfTests(unittest.TestCase): - - def setUp(self): - self.true = TestVar(True) - self.false = TestVar(False) - self.high = TestVar(9000) - self.low = TestVar(1) - - def assertCalc(self, calc, context=None): - """ - Test a calculation is True, also checking the inverse "negate" case. - """ - context = context or {} - self.assert_(calc.resolve(context)) - calc.negate = not calc.negate - self.assertFalse(calc.resolve(context)) - - def assertCalcFalse(self, calc, context=None): - """ - Test a calculation is False, also checking the inverse "negate" case. - """ - context = context or {} - self.assertFalse(calc.resolve(context)) - calc.negate = not calc.negate - self.assert_(calc.resolve(context)) - - def test_or(self): - self.assertCalc(Or(self.true)) - self.assertCalcFalse(Or(self.false)) - self.assertCalc(Or(self.true, self.true)) - self.assertCalc(Or(self.true, self.false)) - self.assertCalc(Or(self.false, self.true)) - self.assertCalcFalse(Or(self.false, self.false)) - - def test_and(self): - self.assertCalc(And(self.true, self.true)) - self.assertCalcFalse(And(self.true, self.false)) - self.assertCalcFalse(And(self.false, self.true)) - self.assertCalcFalse(And(self.false, self.false)) - - def test_equals(self): - self.assertCalc(Equals(self.low, self.low)) - self.assertCalcFalse(Equals(self.low, self.high)) - - def test_greater(self): - self.assertCalc(Greater(self.high, self.low)) - self.assertCalcFalse(Greater(self.low, self.low)) - self.assertCalcFalse(Greater(self.low, self.high)) - - def test_greater_or_equal(self): - self.assertCalc(GreaterOrEqual(self.high, self.low)) - self.assertCalc(GreaterOrEqual(self.low, self.low)) - self.assertCalcFalse(GreaterOrEqual(self.low, self.high)) - - def test_in(self): - list_ = TestVar([1, 2, 3]) - invalid_list = TestVar(None) - self.assertCalc(In(self.low, list_)) - self.assertCalcFalse(In(self.low, invalid_list)) - - def test_parse_bits(self): - var = IfParser([True]).parse() - self.assert_(var.resolve({})) - var = IfParser([False]).parse() - self.assertFalse(var.resolve({})) - - var = IfParser([False, 'or', True]).parse() - self.assert_(var.resolve({})) - - var = IfParser([False, 'and', True]).parse() - self.assertFalse(var.resolve({})) - - var = IfParser(['not', False, 'and', 'not', False]).parse() - self.assert_(var.resolve({})) - - var = IfParser(['not', 'not', True]).parse() - self.assert_(var.resolve({})) - - var = IfParser([1, '=', 1]).parse() - self.assert_(var.resolve({})) - - var = IfParser([1, 'not', '=', 1]).parse() - self.assertFalse(var.resolve({})) - - var = IfParser([1, 'not', 'not', '=', 1]).parse() - self.assert_(var.resolve({})) - - var = IfParser([1, '!=', 1]).parse() - self.assertFalse(var.resolve({})) - - var = IfParser([3, '>', 2]).parse() - self.assert_(var.resolve({})) - - var = IfParser([1, '<', 2]).parse() - self.assert_(var.resolve({})) - - var = IfParser([2, 'not', 'in', [2, 3]]).parse() - self.assertFalse(var.resolve({})) - - var = IfParser([1, 'or', 1, '=', 2]).parse() - self.assert_(var.resolve({})) - - def test_boolean(self): - var = IfParser([True, 'and', True, 'and', True]).parse() - self.assert_(var.resolve({})) - var = IfParser([False, 'or', False, 'or', True]).parse() - self.assert_(var.resolve({})) - var = IfParser([True, 'and', False, 'or', True]).parse() - self.assert_(var.resolve({})) - var = IfParser([False, 'or', True, 'and', True]).parse() - self.assert_(var.resolve({})) - - var = IfParser([True, 'and', True, 'and', False]).parse() - self.assertFalse(var.resolve({})) - var = IfParser([False, 'or', False, 'or', False]).parse() - self.assertFalse(var.resolve({})) - var = IfParser([False, 'or', True, 'and', False]).parse() - self.assertFalse(var.resolve({})) - var = IfParser([False, 'and', True, 'or', False]).parse() - self.assertFalse(var.resolve({})) - - def test_invalid(self): - self.assertRaises(ValueError, IfParser(['not']).parse) - self.assertRaises(ValueError, IfParser(['==']).parse) - self.assertRaises(ValueError, IfParser([1, 'in']).parse) - self.assertRaises(ValueError, IfParser([1, '>', 'in']).parse) - self.assertRaises(ValueError, IfParser([1, '==', 'not', 'not']).parse) - self.assertRaises(ValueError, IfParser([1, 2]).parse) - - -OPERATORS = { - '=': (Equals, True), - '==': (Equals, True), - '!=': (Equals, False), - '>': (Greater, True), - '>=': (GreaterOrEqual, True), - '<=': (Greater, False), - '<': (GreaterOrEqual, False), - 'or': (Or, True), - 'and': (And, True), - 'in': (In, True), -} -BOOL_OPERATORS = ('or', 'and') - - -class IfParser(object): - error_class = ValueError - - def __init__(self, tokens): - self.tokens = tokens - - def _get_tokens(self): - return self._tokens - - def _set_tokens(self, tokens): - self._tokens = tokens - self.len = len(tokens) - self.pos = 0 - - tokens = property(_get_tokens, _set_tokens) - - def parse(self): - if self.at_end(): - raise self.error_class('No variables provided.') - var1 = self.get_bool_var() - while not self.at_end(): - op, negate = self.get_operator() - var2 = self.get_bool_var() - var1 = op(var1, var2, negate=negate) - return var1 - - def get_token(self, eof_message=None, lookahead=False): - negate = True - token = None - pos = self.pos - while token is None or token == 'not': - if pos >= self.len: - if eof_message is None: - raise self.error_class() - raise self.error_class(eof_message) - token = self.tokens[pos] - negate = not negate - pos += 1 - if not lookahead: - self.pos = pos - return token, negate - - def at_end(self): - return self.pos >= self.len - - def create_var(self, value): - return TestVar(value) - - def get_bool_var(self): - """ - Returns either a variable by itself or a non-boolean operation (such as - ``x == 0`` or ``x < 0``). - - This is needed to keep correct precedence for boolean operations (i.e. - ``x or x == 0`` should be ``x or (x == 0)``, not ``(x or x) == 0``). - """ - var = self.get_var() - if not self.at_end(): - op_token = self.get_token(lookahead=True)[0] - if isinstance(op_token, basestring) and (op_token not in - BOOL_OPERATORS): - op, negate = self.get_operator() - return op(var, self.get_var(), negate=negate) - return var - - def get_var(self): - token, negate = self.get_token('Reached end of statement, still ' - 'expecting a variable.') - if isinstance(token, basestring) and token in OPERATORS: - raise self.error_class('Expected variable, got operator (%s).' % - token) - var = self.create_var(token) - if negate: - return Or(var, negate=True) - return var - - def get_operator(self): - token, negate = self.get_token('Reached end of statement, still ' - 'expecting an operator.') - if not isinstance(token, basestring) or token not in OPERATORS: - raise self.error_class('%s is not a valid operator.' % token) - if self.at_end(): - raise self.error_class('No variable provided after "%s".' % token) - op, true = OPERATORS[token] - if not true: - negate = not negate - return op, negate - - -#============================================================================== -# Actual templatetag code. -#============================================================================== - -class TemplateIfParser(IfParser): - error_class = template.TemplateSyntaxError - - def __init__(self, parser, *args, **kwargs): - self.template_parser = parser - return super(TemplateIfParser, self).__init__(*args, **kwargs) - - def create_var(self, value): - return self.template_parser.compile_filter(value) - - -class SmartIfNode(template.Node): - - def __init__(self, var, nodelist_true, nodelist_false=None): - self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false - self.var = var - - def render(self, context): - if self.var.resolve(context): - return self.nodelist_true.render(context) - if self.nodelist_false: - return self.nodelist_false.render(context) - return '' - - def __repr__(self): - return "" - - def __iter__(self): - for node in self.nodelist_true: - yield node - if self.nodelist_false: - for node in self.nodelist_false: - yield node - - def get_nodes_by_type(self, nodetype): - nodes = [] - if isinstance(self, nodetype): - nodes.append(self) - nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype)) - if self.nodelist_false: - nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype)) - return nodes - - -@register.tag('if') -def smart_if(parser, token): - """ - A smarter {% if %} tag for django templates. - - While retaining current Django functionality, it also handles equality, - greater than and less than operators. Some common case examples:: - - {% if articles|length >= 5 %}...{% endif %} - {% if "ifnotequal tag" != "beautiful" %}...{% endif %} - - Arguments and operators _must_ have a space between them, so - ``{% if 1>2 %}`` is not a valid smart if tag. - - All supported operators are: ``or``, ``and``, ``in``, ``=`` (or ``==``), - ``!=``, ``>``, ``>=``, ``<`` and ``<=``. - """ - bits = token.split_contents()[1:] - var = TemplateIfParser(parser, bits).parse() - nodelist_true = parser.parse(('else', 'endif')) - token = parser.next_token() - if token.contents == 'else': - nodelist_false = parser.parse(('endif',)) - parser.delete_first_token() - else: - nodelist_false = None - return SmartIfNode(var, nodelist_true, nodelist_false) - - -if __name__ == '__main__': - unittest.main() +""" +A smarter {% if %} tag for django templates. + +While retaining current Django functionality, it also handles equality, +greater than and less than operators. Some common case examples:: + + {% if articles|length >= 5 %}...{% endif %} + {% if "ifnotequal tag" != "beautiful" %}...{% endif %} +""" +from django import template + + +register = template.Library() + + +#============================================================================== +# Calculation objects +#============================================================================== + +class BaseCalc(object): + + def __init__(self, var1, var2=None, negate=False): + self.var1 = var1 + self.var2 = var2 + self.negate = negate + + def resolve(self, context): + try: + var1, var2 = self.resolve_vars(context) + outcome = self.calculate(var1, var2) + except: + outcome = False + if self.negate: + return not outcome + return outcome + + def resolve_vars(self, context): + var2 = self.var2 and self.var2.resolve(context) + return self.var1.resolve(context), var2 + + def calculate(self, var1, var2): + raise NotImplementedError() + + +class Or(BaseCalc): + + def calculate(self, var1, var2): + return var1 or var2 + + +class And(BaseCalc): + + def calculate(self, var1, var2): + return var1 and var2 + + +class Equals(BaseCalc): + + def calculate(self, var1, var2): + return var1 == var2 + + +class Greater(BaseCalc): + + def calculate(self, var1, var2): + return var1 > var2 + + +class GreaterOrEqual(BaseCalc): + + def calculate(self, var1, var2): + return var1 >= var2 + + +class In(BaseCalc): + + def calculate(self, var1, var2): + return var1 in var2 + + +OPERATORS = { + '=': (Equals, True), + '==': (Equals, True), + '!=': (Equals, False), + '>': (Greater, True), + '>=': (GreaterOrEqual, True), + '<=': (Greater, False), + '<': (GreaterOrEqual, False), + 'or': (Or, True), + 'and': (And, True), + 'in': (In, True), +} +BOOL_OPERATORS = ('or', 'and') + + +class IfParser(object): + error_class = ValueError + + def __init__(self, tokens): + self.tokens = tokens + + def _get_tokens(self): + return self._tokens + + def _set_tokens(self, tokens): + self._tokens = tokens + self.len = len(tokens) + self.pos = 0 + + tokens = property(_get_tokens, _set_tokens) + + def parse(self): + if self.at_end(): + raise self.error_class('No variables provided.') + var1 = self.get_bool_var() + while not self.at_end(): + op, negate = self.get_operator() + var2 = self.get_bool_var() + var1 = op(var1, var2, negate=negate) + return var1 + + def get_token(self, eof_message=None, lookahead=False): + negate = True + token = None + pos = self.pos + while token is None or token == 'not': + if pos >= self.len: + if eof_message is None: + raise self.error_class() + raise self.error_class(eof_message) + token = self.tokens[pos] + negate = not negate + pos += 1 + if not lookahead: + self.pos = pos + return token, negate + + def at_end(self): + return self.pos >= self.len + + def create_var(self, value): + raise NotImplementedError() + + def get_bool_var(self): + """ + Returns either a variable by itself or a non-boolean operation (such as + ``x == 0`` or ``x < 0``). + + This is needed to keep correct precedence for boolean operations (i.e. + ``x or x == 0`` should be ``x or (x == 0)``, not ``(x or x) == 0``). + """ + var = self.get_var() + if not self.at_end(): + op_token = self.get_token(lookahead=True)[0] + if isinstance(op_token, basestring) and (op_token not in + BOOL_OPERATORS): + op, negate = self.get_operator() + return op(var, self.get_var(), negate=negate) + return var + + def get_var(self): + token, negate = self.get_token('Reached end of statement, still ' + 'expecting a variable.') + if isinstance(token, basestring) and token in OPERATORS: + raise self.error_class('Expected variable, got operator (%s).' % + token) + var = self.create_var(token) + if negate: + return Or(var, negate=True) + return var + + def get_operator(self): + token, negate = self.get_token('Reached end of statement, still ' + 'expecting an operator.') + if not isinstance(token, basestring) or token not in OPERATORS: + raise self.error_class('%s is not a valid operator.' % token) + if self.at_end(): + raise self.error_class('No variable provided after "%s".' % token) + op, true = OPERATORS[token] + if not true: + negate = not negate + return op, negate + + +#============================================================================== +# Actual templatetag code. +#============================================================================== + +class TemplateIfParser(IfParser): + error_class = template.TemplateSyntaxError + + def __init__(self, parser, *args, **kwargs): + self.template_parser = parser + return super(TemplateIfParser, self).__init__(*args, **kwargs) + + def create_var(self, value): + return self.template_parser.compile_filter(value) + + +class SmartIfNode(template.Node): + + def __init__(self, var, nodelist_true, nodelist_false=None): + self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false + self.var = var + + def render(self, context): + if self.var.resolve(context): + return self.nodelist_true.render(context) + if self.nodelist_false: + return self.nodelist_false.render(context) + return '' + + def __repr__(self): + return "" + + def __iter__(self): + for node in self.nodelist_true: + yield node + if self.nodelist_false: + for node in self.nodelist_false: + yield node + + def get_nodes_by_type(self, nodetype): + nodes = [] + if isinstance(self, nodetype): + nodes.append(self) + nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype)) + if self.nodelist_false: + nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype)) + return nodes + + +@register.tag('if') +def smart_if(parser, token): + """ + A smarter {% if %} tag for django templates. + + While retaining current Django functionality, it also handles equality, + greater than and less than operators. Some common case examples:: + + {% if articles|length >= 5 %}...{% endif %} + {% if "ifnotequal tag" != "beautiful" %}...{% endif %} + + Arguments and operators _must_ have a space between them, so + ``{% if 1>2 %}`` is not a valid smart if tag. + + All supported operators are: ``or``, ``and``, ``in``, ``=`` (or ``==``), + ``!=``, ``>``, ``>=``, ``<`` and ``<=``. + """ + bits = token.split_contents()[1:] + var = TemplateIfParser(parser, bits).parse() + nodelist_true = parser.parse(('else', 'endif')) + token = parser.next_token() + if token.contents == 'else': + nodelist_false = parser.parse(('endif',)) + parser.delete_first_token() + else: + nodelist_false = None + return SmartIfNode(var, nodelist_true, nodelist_false) diff --git a/sigi/apps/diagnosticos/templatetags/test_smart_if.py b/sigi/apps/diagnosticos/templatetags/test_smart_if.py new file mode 100644 index 0000000..9101bf9 --- /dev/null +++ b/sigi/apps/diagnosticos/templatetags/test_smart_if.py @@ -0,0 +1,166 @@ +# -*- coding: utf-8 -*- +import pytest + +from smart_if import Or, And, Equals, Greater, GreaterOrEqual, In, IfParser + + +class TestVar(object): + + """ + A basic self-resolvable object similar to a Django template variable. Used + to assist with tests. + """ + + def __init__(self, value): + self.value = value + + def resolve(self, context): + return self.value + + +class TestIfParser(IfParser): + + def create_var(self, value): + return TestVar(value) + + +class ValueHolder(object): + pass + +VALORES = ValueHolder() +VALORES.true = TestVar(True) +VALORES.false = TestVar(False) +VALORES.high = TestVar(9000) +VALORES.low = TestVar(1) + + +def assertCalc(calc, context=None): + """ + Test a calculation is True, also checking the inverse "negate" case. + """ + context = context or {} + assert calc.resolve(context) + calc.negate = not calc.negate + assert not calc.resolve(context) + + +def assertCalcFalse(calc, context=None): + """ + Test a calculation is False, also checking the inverse "negate" case. + """ + context = context or {} + assert not calc.resolve(context) + calc.negate = not calc.negate + assert calc.resolve(context) + + +def test_or(): + assertCalc(Or(VALORES.true)) + assertCalcFalse(Or(VALORES.false)) + assertCalc(Or(VALORES.true, VALORES.true)) + assertCalc(Or(VALORES.true, VALORES.false)) + assertCalc(Or(VALORES.false, VALORES.true)) + assertCalcFalse(Or(VALORES.false, VALORES.false)) + + +def test_and(): + assertCalc(And(VALORES.true, VALORES.true)) + assertCalcFalse(And(VALORES.true, VALORES.false)) + assertCalcFalse(And(VALORES.false, VALORES.true)) + assertCalcFalse(And(VALORES.false, VALORES.false)) + + +def test_equals(): + assertCalc(Equals(VALORES.low, VALORES.low)) + assertCalcFalse(Equals(VALORES.low, VALORES.high)) + + +def test_greater(): + assertCalc(Greater(VALORES.high, VALORES.low)) + assertCalcFalse(Greater(VALORES.low, VALORES.low)) + assertCalcFalse(Greater(VALORES.low, VALORES.high)) + + +def test_greater_or_equal(): + assertCalc(GreaterOrEqual(VALORES.high, VALORES.low)) + assertCalc(GreaterOrEqual(VALORES.low, VALORES.low)) + assertCalcFalse(GreaterOrEqual(VALORES.low, VALORES.high)) + + +def test_in(): + list_ = TestVar([1, 2, 3]) + invalid_list = TestVar(None) + assertCalc(In(VALORES.low, list_)) + assertCalcFalse(In(VALORES.low, invalid_list)) + + +def test_parse_bits(): + var = TestIfParser([True]).parse() + assert var.resolve({}) + var = TestIfParser([False]).parse() + assert not var.resolve({}) + + var = TestIfParser([False, 'or', True]).parse() + assert var.resolve({}) + + var = TestIfParser([False, 'and', True]).parse() + assert not var.resolve({}) + + var = TestIfParser(['not', False, 'and', 'not', False]).parse() + assert var.resolve({}) + + var = TestIfParser(['not', 'not', True]).parse() + assert var.resolve({}) + + var = TestIfParser([1, '=', 1]).parse() + assert var.resolve({}) + + var = TestIfParser([1, 'not', '=', 1]).parse() + assert not var.resolve({}) + + var = TestIfParser([1, 'not', 'not', '=', 1]).parse() + assert var.resolve({}) + + var = TestIfParser([1, '!=', 1]).parse() + assert not var.resolve({}) + + var = TestIfParser([3, '>', 2]).parse() + assert var.resolve({}) + + var = TestIfParser([1, '<', 2]).parse() + assert var.resolve({}) + + var = TestIfParser([2, 'not', 'in', [2, 3]]).parse() + assert not var.resolve({}) + + var = TestIfParser([1, 'or', 1, '=', 2]).parse() + assert var.resolve({}) + + +def test_boolean(): + var = TestIfParser([True, 'and', True, 'and', True]).parse() + assert var.resolve({}) + var = TestIfParser([False, 'or', False, 'or', True]).parse() + assert var.resolve({}) + var = TestIfParser([True, 'and', False, 'or', True]).parse() + assert var.resolve({}) + var = TestIfParser([False, 'or', True, 'and', True]).parse() + assert var.resolve({}) + + var = TestIfParser([True, 'and', True, 'and', False]).parse() + assert not var.resolve({}) + var = TestIfParser([False, 'or', False, 'or', False]).parse() + assert not var.resolve({}) + var = TestIfParser([False, 'or', True, 'and', False]).parse() + assert not var.resolve({}) + var = TestIfParser([False, 'and', True, 'or', False]).parse() + assert not var.resolve({}) + + +def test_invalid(): + pytest.raises(ValueError, TestIfParser(['not']).parse) + pytest.raises(ValueError, TestIfParser(['==']).parse) + pytest.raises(ValueError, TestIfParser([1, 'in']).parse) + pytest.raises(ValueError, TestIfParser([1, '>', 'in']).parse) + pytest.raises(ValueError, TestIfParser([1, '==', 'not', 'not']).parse) + pytest.raises(ValueError, TestIfParser([1, 2]).parse) diff --git a/sigi/settings/base.py b/sigi/settings/base.py index eb2c5b3..d35bea5 100644 --- a/sigi/settings/base.py +++ b/sigi/settings/base.py @@ -111,3 +111,5 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/' SESSION_EXPIRE_AT_BROWSER_CLOSE = True + +TEST_RUNNER = None diff --git a/sigi/settings/test.py b/sigi/settings/test.py new file mode 100644 index 0000000..b742c3a --- /dev/null +++ b/sigi/settings/test.py @@ -0,0 +1,16 @@ +from base import * + + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '0$ip1fb5xtq%a=)-k_4r^(#jn0t^@+*^kihkxkozg-mip7+w3+' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'sigi_test', + 'USER': 'sigi', + 'PASSWORD': 'sigi', + 'HOST': 'localhost', + 'PORT': '5432', + } +}