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-devel@xxxxxxxxxxxxxxxxxxxxxxx https://admin.fedoraproject.org/mailman/listinfo/389-devel