Wednesday, 15 September 2010

python - Test pollution in unittest -



python - Test pollution in unittest -

this question has reply here:

“least astonishment” in python: mutable default argument 28 answers

i have 2 functions, apply_rule , match. each defined independently - don't belong class.

match takes 2 required paramters, , optional parameter, called pairs. defaults empty dictionary. below code apply_rule , match. note match called, , optional parameter pairs isn't specified.

def apply_rule(pat, rule): if not isrule(rule): homecoming "not valid rule" subs = match(lhs(rule), pat) if subs == {}: homecoming pat else: homecoming substitute(rhs(rule), subs) def match(pat, lst, pairs={}): if pat == [] , lst == []: homecoming pairs elif isvariable(pat[0]): if pat[0] not in pairs.keys(): pairs[pat[0]] = lst[0] elif pat[0] in pairs.keys() , lst[0] != pairs[pat[0]]: homecoming false elif pat[0] != lst[0]: homecoming false homecoming match(pat[1:], lst[1:], pairs)

right now, unittest match fails, because "remembers" pairs, defined in test apply_rule.

however, if alter 3rd line in apply_rule subs = match(lhs(rule), pat, {})then tests pass. do know why? far can tell, there shouldn't way match remembers value of pairs when called in other tests.

below unit tests, reference.

def test_match(self): self.assertequal({}, match(['a', 'b', 'c'], ['a', 'b', 'c'])) self.assertequal(self.dict_with_x, match(['a', '_x', 'c'], ['a', '5', 'c'])) self.assertequal(self.dict_with_x, match(self.pat_with_xx, self.list_with_55)) self.assertequal(self.dict_with_xy, match(self.pat_with_xy, self.list_with_5hi)) self.assertfalse(match(self.pat_with_xx, ['a', 'b', 'c', 'd'])) self.assertfalse(match(['a', 'b', 'c'], ['a', 'b', 'd'])) def test_apply_and_firerule(self): pattern1 = "my mother thinks fat".split(' ') expected = "do think fat ?".split(' ') self.assertequal(apply_rule(pattern1, self.r1), expected)

and failure message...

traceback (most recent phone call last): file "pattern_matcher_tests.py", line 65, in test_match self.assertequal({}, match(['a', 'b', 'c'], ['a', 'b', 'c'])) assertionerror: {} != {'_y': 'fat', '_x': 'mother'} - {} + {'_x': 'mother', '_y': 'fat'}

from effbot

why happen? #

default parameter values evaluated when, , when, “def” statement belong executed; see:

http://docs.python.org/ref/function.html

for relevant section in language reference.

what instead? #

the workaround is, others have mentioned, utilize placeholder value instead of modifying default value. none mutual value:

python unit-testing

No comments:

Post a Comment