larry-discuss team mailing list archive
-
larry-discuss team
-
Mailing list archive
-
Message #00022
Re: [Blueprint simplify-unit-testing] Create a larry specific assert function to simplify unit testing
On Thu, Feb 4, 2010 at 11:17 AM, Keith Goodman <kwgoodman@xxxxxxxxx> wrote:
> On Thu, Feb 4, 2010 at 8:04 AM, <josef.pktd@xxxxxxxxx> wrote:
>> On Thu, Feb 4, 2010 at 10:33 AM, Keith Goodman <kwgoodman@xxxxxxxxx> wrote:
>>> On Wed, Feb 3, 2010 at 7:04 PM, <josef.pktd@xxxxxxxxx> wrote:
>>>> On Wed, Feb 3, 2010 at 9:54 PM, <josef.pktd@xxxxxxxxx> wrote:
>>>>> On Wed, Feb 3, 2010 at 9:16 PM, Keith Goodman <kwgoodman@xxxxxxxxx> wrote:
>>>>>> On Wed, Feb 3, 2010 at 6:06 PM, joep <josef.pktd@xxxxxxxxx> wrote:
>>>>>>> Blueprint changed by joep:
>>>>>>>
>>>>>>> Whiteboard set to:
>>>>>>>
>>>>>>> assert_larry
>>>>>>> http://bazaar.launchpad.net/~kwgoodman/larry/trunk/annotate/head%3A/la/tests/deflarry_nose_test.py#L49
>>>>>>>
>>>>>>> and the method check_function in test class
>>>>>>>
>>>>>>> http://bazaar.launchpad.net/~kwgoodman/larry/trunk/annotate/head%3A/la/tests/deflarry_nose_test.py#L128
>>>>>>>
>>>>>>> already contain the extracted boiler plate assert function to compare a
>>>>>>> larry with desired data matrix x and labels
>>>>>>>
>>>>>>> the later has a view keyword to choose whether to verify nocopy or
>>>>>>> noreference
>>>>>>>
>>>>>>> used in nosetests for larry methods
>>>>>>
>>>>>> I moved this to the larry-discuss list since it is hard to discuss it
>>>>>> through the whiteboard on the blueprint.
>>>>>>
>>>>>> Yes, let's start with those functions and then prettify them.
>>>>>>
>>>>>> What should the signature be?
>>>>>>
>>>>>> The current signature is:
>>>>>>
>>>>>> assert_larry(opname, la, t, lab, msgstr)
>>>>>>
>>>>>> How about changing that to the same signature as np.testing.assert_equal? So:
>>>>>>
>>>>>> assert_equal(actual, desired, err_msg='', verbose=True)
>>>>>>
>>>>>> Then we don't have to separate the data and the label. And instead of
>>>>>> nancode we can use the numpy nan aware assert in numpy 1.4.
>>>>>>
>>>>>> Oops...dinner time!
>>>>>
>>>>> I'm just browsing the code and adding some notes.
>>>>>
>>>>> Yes, matching the numpy signature for assert_equal and
>>>>> assert_almost_equal is a good idea.
>>>>> If you require numpy 1.4 for the test suite, then most of the boiler
>>>>> plate is gone (nan handling)
>>>>>
>>>>> I think that assert_larry_equal is equivalent to
>>>>> assert_equal(la1.x, la2.x)
>>>>> assert_equal(la1.label, la2.label)
>>>>>
>>>>> slicing_test.py/test_slicing and test_morph use directly an assert_
>>>>> which could be replaced by np.testing.assert_equal
>>>>
>>>> just another comment:
>>>>
>>>> there are 3 patterns in the test suite corresponding to the previous comments
>>>>
>>>> * python unittest with boilerplate
>>>> * numpy 1.3 nosetests with explicit nan handling
>>>> * numpy 1.4 nosetests where numpy.testing assert do the nan handling
>>>>
>>>> In the 4th option an explicit function assert_larry_xxx is not really
>>>> necessary, and the test for x and labels and nocopy/noreference could
>>>> also be "yielded" directly from the test function/method.
>>>
>>> Instead of making many unit tests out of one call to larry's
>>> assert_equal, which would occur if we used yield, I think it is better
>>> for the whole thing be one unit test. That would mean that we'd have
>>> to wrap calls to np.testing.assert_equal in try...except blocks,
>>> collect any error messages, and raise an AssertionError at the end of
>>> the function if needed.
>>
>> several asserts don't have to be yielded, if you want them to be only
>> one unittest that fails at the first assertion error, e.g.
>> def test_movingsum32(self) in deflarry_nose_test.py
>
> I think it is better for debugging if all the info is printed out when
> the test fails. For example, if a test fails on the label, Id like to
> know if it passed on the array.
>
>>>
>>> As for signature, how about
>>>
>>> assert_equal(actual, desired, msg='', dtype=True, noreference=True,
>>> nocopy=False, verbose=True)
>>
>> this doesn't work, since noreference and nocopy also need the original larry,
>> the signature of check function is
>
> Good point.
>
> An alternative to passing in the original and the actual is to pass in
> the original and the function that modifies the original to produce
> the actual. Then two larrys are always passed in. But that sounds
> messy.
>
>> check_function(self, t, label, p, orig, view=False)
>>
>> the signature could be
>> assert_larry_equal(actual, desired, msg='', dtype=True, original=None,
>> noreference=True,
>> nocopy=False, verbose=True)
>
> Should we go with the signature above?
>
>> but for noreference=True check an original has to be included
>>
>> with
>> assert_larry_equal(actual, desired, original, msg='', dtype=True,
>> noreference=True,
>> nocopy=False, verbose=True)
>>
>> the original would have to be passed in even if both noreference and
>> nocopy are False
>>
>>
>>> So by default the dtype would be compared. Sometimes you expect the
>>> dtype to change so maybe an option would be to pass in the dtype for
>>> the "desired" larry.
>>>
>>> I think that would cover the most common use cases.
>>
>> Yes, I think so for the comparison of two larrys
>>
>> slicing tests e.g. test_slicing, would need a new function for
>> noreference, nocopy that verifies e.g. that a slice is really a view.
>> (I don't know what the numpy tests for view versus copy are for fancy
>> slicing/indexing)
>>
>> Josef
I attached a draft of the assert_larry_equal function. it imports some
helper functions from test.py in the la/tests folder, which
could/should also be rewritten into assert form.
It's a draft, I haven't checked if it is working correctly yet for all cases.
Also, I think it would be better to add the testing helper functions
to la.utils so that they can be imported and don't need to have a copy
in the test folder, as in the case of test.py.
Josef
>>
>>>
>>> _______________________________________________
>>> Mailing list: https://launchpad.net/~larry-discuss
>>> Post to : larry-discuss@xxxxxxxxxxxxxxxxxxx
>>> Unsubscribe : https://launchpad.net/~larry-discuss
>>> More help : https://help.launchpad.net/ListHelp
>>>
>>
>> _______________________________________________
>> Mailing list: https://launchpad.net/~larry-discuss
>> Post to : larry-discuss@xxxxxxxxxxxxxxxxxxx
>> Unsubscribe : https://launchpad.net/~larry-discuss
>> More help : https://help.launchpad.net/ListHelp
>>
>
# -*- coding: utf-8 -*-
"""
Created on Tue Dec 22 23:42:40 2009
Author: josef-pktd
"""
import numpy as np
from la import larry
nan = np.nan
def dup23(x):
'''convert 2d to 3d array to compare axis=0 with axis=2 for reduce
operations
see dup23_
'''
return np.rollaxis(np.dstack([x,x]),2)
#label3 = [[0,1], [0, 1, 2], [0, 1, 2, 3]]
label3 = [[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5],
[0,1]]
x = np.array([[0.0, 3.0, nan, nan, 0.0, nan],
[1.0, 1.0, 1.0, nan, nan, nan],
[2.0, 2.0, 0.0, nan, 1.0, nan],
[3.0, 0.0, 2.0, nan, nan, nan],
[4.0, 4.0, 3.0, 0.0, 2.0, nan],
[5.0, 5.0, 4.0, 4.0, nan, nan]])
sectorsli = ['a', 'b', 'a', 'b', 'a', 'c']
#labels = [[0, 1, 2, 3, 4, 5], sectors]
lar = larry(x)
sectors = larry(np.array(sectorsli, dtype=object))
lar3 = larry(dup23(lar.x).T)
lar3b = larry(np.dstack([x,x]))
label = [[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]
from numpy.testing import assert_, assert_equal
from test import printfail
from test import noreference as assert_noreference
from test import nocopy as assert_nocopy
def assert_larry_equal(actual, desired, msg='', dtype=True, original=None,
noreference=True, nocopy=False, verbose=True):
#assert equality of attributes of two larries
msg = printfail(actual.x, desired.x, 'x')
assert_equal(actual.x, desired.x, msg)
msg = printfail(actual.label, desired.label, 'label')
assert_equal(actual.label, desired.label, msg)
if dtype:
msg = printfail(actual.x.dtype, desired.x.dtype, 'x.dtype')
assert(actual.x.dtype, desired.x.dtype, msg)
if noreference:
assert_(assert_noreference(actual, original), 'Reference found')
elif nocopy:
assert_(assert_nocopy(actual, original), 'copy instead of reference found')
else: #FIXME check view for different dimensional larries
pass
lar3b0, lar3b1 = lar3b[:,:,0], lar3b[:,:,1]
assert_larry_equal(lar3b0, lar3b1, noreference=False)
assert_larry_equal(lar3b0, lar3b1, original=lar, noreference=True)
Follow ups
References