Tests for Python Data Structure Base Interfaces

A pretty little question: does anyone know about a ready-made package of Python unit tests that simply check if a class matches one of the standard Python data structure interfaces (e.g. lists, sets, dictionaries, queues, etc.)., It's not too much itโ€™s hard to write, but I wouldnโ€™t want to do this if someone had already done it. This looks like a very basic functionality that someone has already done already.

A use case is that I am using the factory template to create data structures due to various platform restrictions. Thus, I need to be able to verify that the resulting created objects still match the standard interfaces on the surface. In addition, I should note that by "conformity" I mean that tests should check not only the functions of the interface, but also verify that they work (for example, they can set and retrieve the value on the map, for example). Python 2.7 tests would be preferable.

+4
source share
2 answers

First, the "standard Python data structure interfaces" are not lists, sets, dictionaries, queues, etc. These are specific implementations of interfaces. (And the queue is not even a data structure in the sense that you are thinking about - its characteristic features are that its operations are atomic, and put and get not necessarily synchronized on Condition , etc.).

In either case, the interfaces are defined in five different incompatible ways.


The Built-in Types section in the documentation describes what it means to be an iterator type, sequence type, etc. However, these are not as strict as you would expect for reference documentation (at least if you are used to, say, C ++ or Java).

I do not know any tests for such a thing, so I think that you will have to build them from scratch.


The collections module contains Collections Abstract base classes that define interfaces and provide a way to register "virtual subclasses" through the abc module . That way you can declare โ€œI am a mappingโ€ by inheriting from collections.Mapping or by calling collections.Mapping.register . But this does not really prove that you are a mapping, that is what you say. (If you inherit from Mapping , it also acts as a mixin, which helps you complete the interface by implementing, for example, __contains__ on top of __getitem__ .)

If you want to check the value of ABC, the defuz answer is very close, and with a bit of work, I think that he or someone else can complete this.


The CPython C API defines the Abstract Level of Objects . Although this, in fact, is not authoritative for this language, it is obvious that it is assumed that the C-API protocols and interfaces at the language level must comply. And, unlike the latter, the former are strictly defined. And of course, the source code for CPython 2.7 , and possibly other implementations like PyPy , might help.

There are tests for this that come with CPython, but they are actually designed to test that calling PyMapping_GetItem from C correctly calls your mymapping.__getitem__ in Python, which is really tangent to what you want to test, so I don't I think this will help.


Actual concrete classes have an additional interface on top of protocols that you can test, but this is more difficult to describe. In particular, the __new__ and __init__ methods often work. Implementing the Mapping protocol means that someone can build an empty instance of Foo and add elements to it using foo[key] = value , but this does not mean that someone can build Foo(key=value) or Foo({key: value}) or Foo([(key, value)]) .

And for this case, there are existing tests that come with all standard Python implementations. CPython comes with a very extensive test suite that includes things like test_dict.py . PyPy runs all of the CPython tests at the Python level and some additional ones.

You will obviously have to modify these tests to run on an arbitrary class instead of the one hard-coded in the test, and you may also need to modify them to handle any definition you choose. In addition, they are probably experiencing more than you requested. You just want to know if the class conforms to the protocol, and not about whether its methods do the right thing, right? But still, I think they are a good starting point.


Finally, the C API defines a Concrete Objects Layer , which, although not authoritative, meets the previous definition and is more strictly defined.

Unfortunately, the tests for this will definitely not be very useful for you, because they check things like PyDict_Check and PyDict_GetItem work on your class that they will not be for any display defined in pure Python.


If you create something complete for any of these definitions, I would strongly suggest posting it on PyPI and posting it to the python list so that you get feedback (and error reports).

+3
source

abstract base classes in the standard collections module based on the ABC module.

You must inherit your classes from these classes to make sure your classes conform to standard behavior:

 import collections class MyDict(collections.Mapping): ... 

In addition, you can check an existing class that does not explicitly inherit the abstract class:

 class MyPerfectDict(object): ... realization ... def is_inherit(cls, abstract): try: class Test(abstract, cls): pass test = Test() except TypeError: return False else: return True is_inherit(MyPerfectDict, Mapping) # False is_inherit(dict, Mapping) # True 
0
source

Source: https://habr.com/ru/post/1481238/


All Articles