On 10/29/2013 03:30 PM, thierry bordaz wrote:
> On 10/29/2013 02:18 PM, Jan Rusnacko wrote:
>> Hello Thierry,
>>
>> I am not rewriting ldapadd,... methods of "real" DS class, I am in fact
>> creating MockDS class with custom ldapadd,... methods, _just_ like you
>> suggest :)
>>
>> Furthermore, you can view it as a subclass of "real_ds" - even though it is
>> not
>> a proper Python subclass, it inherits all functions from repl module just
>> like
>> "real_ds" would (again through ModuleProxy mechanism). So, methods that are
>> defined in repl are the same for "real_ds" class and for MockDS class, but
>> ldap.. methods are different. So, basically exactly what you suggest :)
>
> Hi Jan,
>
> Sorry my question was not clear. For example an other approach could be
>
> Class DSInstance (object):
> def __init__(self):
> ...
>
> def ldapadd_r(self, input):
> # real call to pythonldap.add_s
>
> Class MockDSInstance(DSInstance):
> def __init__(self):
> ...
>
> def ldapadd_r(self, input):
> input = input.strip()
> entry = dict(e.strip().split(': ') for e in input.split('\n'))
> self.dit[entry['dn']] = entry
>
>
>
> My understanding is that both approach would allow us to call inherited
> methods, just ldap method are different.
> What are the advantages of the approach you described compare to the one
> above ?
Oh, ok. Not sure what would be advantage/disadvantage. Result of both approaches
is basically the same ... We could do it this way too.
>
> best regards
> thierry
>>
>> Code of the whole class along with all methods is in file
>> tests/test_dsmodules/conftest.py line 7.
>>
>> Thank you,
>> Jan
>>
>> On 10/28/2013 12:02 PM, thierry bordaz wrote:
>>> Hi Jan,
>>>
>>> That is very impressive POC, far above my skill in python. Thanks for
>>> sharing this.
>>> I have a novice question.
>>> This implementation overwrites the basic ldapadd,ldapsearch... function
>>> of
>>> the "real" DS.
>>> An other approach is to write a 'mock_ds' class being a subclass of
>>> 'real_ds' and to overwrite the ldapadd,ldapsearch in mock_ds class (to
>>> store
>>> data into a dict). What would be the advantages of your approach ?
>>>
>>> best regards
>>> thierry
>>>
>>> On 10/25/2013 09:36 PM, Jan Rusnacko wrote:
>>>> Hello Roberto and Thierry,
>>>>
>>>> as I promised, I am sending you a proof-of-concept code that demonstrates,
>>>> how
>>>> we can mock DS in unit tests for library function (see attachment). You
>>>> can run
>>>> tests just by executing py.test in tests directory.
>>>>
>>>> Only 3 files are of interest here:
>>>>
>>>> lib389/dsmodules/repl.py - this is a Python module with functions - they
>>>> expect
>>>> DS instance as the first argument. Since they are functions, not methods,
>>>> I can
>>>> just mock DS and pass that fake one as the first argument to them in unit
>>>> tests.
>>>>
>>>> tests/test_dsmodules/conftest.py - this file contains definition of mock DS
>>>> class along with py.test fixture, that returns it.
>>>>
>>>> tests/test_dsmodules/test_repl.py - this contains unit tests for functions
>>>> from
>>>> repl.py.
>>>>
>>>> What I do is quite simple - I override ldapadd, ldapdelete .. methods of
>>>> mock DS
>>>> class, so that instead of sending command to real DS instance, they just
>>>> store
>>>> the data in 'dit' dictionary (which represents content stored in DS). This
>>>> way,
>>>> I can check that when I call e.g. function enable_changelog(..), in the
>>>> end DS
>>>> will have correct changelog entry.
>>>>
>>>> To put it very bluntly - enable_changelog(..) function just adds correct
>>>> changelog entry to whatever is passed to it as the first argument. In unit
>>>> tests, it is mock DS, otherwise it would be real DS class that sends real
>>>> ldap
>>>> commands to real DS instance behind.
>>>>
>>>> Now I can successfully test that enable_changelog really works, without
>>>> going
>>>> into trouble defining DSInstance or ldap calls at all. Also, I believe this
>>>> approach would work for 95% of all functions in lib389. Another benefit is
>>>> that
>>>> unit tests are much faster, than on real DS instance.
>>>>
>>>> Sidenote: even though everything is defined in separate namespace of 'repl'
>>>> module as function, in runtime they can be used as normal methods of class
>>>> DSInstance. That is handled by DSModuleProxy. We already went through
>>>> this, but
>>>> not with Roberto.
>>>>
>>>> Hopefully, now with some code in our hands, we will be able to understand
>>>> each
>>>> other on this 'mocking' issue and come to conclusions more quickly.
>>>>
>>>> Let me know what you think.
>>>>
>>>> Thank you,
>>>> Jan
>
--
389-devel mailing list
389-de...@lists.fedoraproject.org
https://admin.fedoraproject.org/mailman/listinfo/389-devel