3

I am currently writing some test cases in python. I often end up calling the same two or three lines of code at the start of a test case in order to get the program I am testing going. For example:

test_something_foo():
    call_method_a(x)
    call_method_b(y)
    # test some stuff

test_something_bar():
    call_method_a(x)
    call_method_b(y)
    # test some other stuff

This means I am repeating those two lines together over and over. So I thought to extract like so:

test_something_foo():
    call_method_a_and_b(x,y)
    # test some stuff

test_something_bar():
    call_method_a_and_b(x,y)
    # test some other stuff

call_method_a_and_b(x, y):
    call_method_a()
    call_method_b()

But I am not sure if this is a good idea. On the one hand it solves the "don't repeat yourself" principle, but doesn't my method "call_method_a_and_b()" violate the principle of "a method should do one thing, and one thing only". How do you reconcile those two seemingly conflicting design principles??

1
  • 2
    What are A and B are in this case? Balancing principals is often a matter of context. Commented Mar 12, 2015 at 1:24

2 Answers 2

2

This is what setUp is for. It is executed automatically before running each test, and can be used to initialize class fields and properties or set up the environment (in a case of integration and system tests).

As for the one thing principle, it is perfectly fine to have a method A which calls methods B and C if the method A is acting on a different level of abstraction than B and C.

What would be a violation of one thing principle is to put the bodies of the method B and C inside the method A.

Example: in order to create a product, you need to:

  1. Store the product in the database,

  2. Store the product image on disk.

Those two actions can be put in a method createProduct implemented like this:

def createProduct(self):
    self.db.storeProduct(product_model)
    self.moveImage(product_model.image_upload_path)

The method createProduct performs one thing: it creates a product. On the other hand, if the method actually went in the details of database manipulation and files storage, then it would be doing multiple things.

2

If you can think of a better name than call_method_a_and_b(), a name that is a single concept, then it isn't a violation of the 'one thing' principle.

If you are calling a and b in that order for different reasons in foo than in bar, so one of the two call sites might need to change while the other stays the same, then you aren't violating DRY. (For instance, foo might need to change to call b and then a, while bar needs to keep the original order.)

So, evaluate whether it is a coincidence that you're calling a and b in that order, or whether the pair of them in that order represents an idea or concept. Don't make a method if it's a coincidence, and do if it's an idea. Just make sure not to name the method call_method_a_and_b().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.