简体   繁体   中英

What is the correct way to test classes in Python?

There is a class named State that has several attributes, which I need to write unit tests for. The test will need to have certain actions that change attribute values of the State instance. Expected parameters are located inside of the dictionary. The unit test will compare the attributes of the State instance with the values of the dictionary for equality.

The question is what is the best place to keep the comparison logic at? I was thinking about 2 options:

  1. Add __eq__ method to the State class that contains comparison logic.
  2. Add helper function inside of the test module that contains comparison logic.

Which one of the options is better and why?

Outside. __eq__ should (in most cases) not be used to compare a specific object to a dict and give equality. The expected behaviour is to enable comparison between objects of the same (or inherited) type. If you're looking for a way to compare to State objects, it could be useful - but that doesn't seem to be the case here, according to your description.

I'd also be careful about using __eq__ for specific tests if these tests do not explicitly test for equality , but for certain properties. A future change in __eq__ - ie the comparison requirement between objects of the same class, may not be have the same semantic meaning as what you're actually testing in your test . For example; a future change to __eq__ could introduce more similarity requirements than what your tests require (for example; are they actually the same object and not just similar). Since the expected behaviour for __eq__ is "this represents exactly the same thing", that may not be the same as what you're testing.

Keep the comparison outside of your class - and if it's something you want to re-use in different contexts, either add it as a utility function in your project or add it as a specific function to your object. For now I'd just go with keeping it in your tests, and then moving it inside your project when it becomes necessary .

This all assumes that the comparison is simple . If there is actual logic and calculations involved - that does not belong in the test. Instead, add logic to your class that exposes the values directly in a properly testable format.

A test should just check that the value returned matches what was expected. However, comparing a returned dict against expected values for that dict is perfectly valid.

You should probably take the __eq__ approach. This way you can also test for equality in the actual code in the future if necessary, while also being able to avoid a potentially messy situation with importing the helper function if you plan or might use type annotations in the future.

Generally you do not want your testing code to contain much logic at all, since test are meant to test code not implement more logic which may need to be tested itself. Beyond the actual test functions you test suites should be really very simple.

The only reason I can think to not take this approach is if the class you are testing has some unique use case where a __eq__ is not applicable and you want to avoid implementing one and potentially confusing yourself or future developers later on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM