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 :)

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

Reply via email to