Search code examples
pythonunit-testingmockingevent-handlingtdd

How to define a "limit test context" using TDD?


How to I can define the "limit context" of my tests?

I say this because of mocks, where my service has many other libs integrated, like: rabbit-mq, redis, etc, and instances from some one classes. Then, the greather part of time I'm writing test code, creating "complex" mocks to the service be possible to test.

Is possible defines this limit? Should be a possible way "no test" theses "expensive" method, and just test the "simple related method", that are simple to input the paramters, like a sum(a, b).

Is obvious that the more test coverage the better, but is many, many time writing some tests with a questionable useful result.

When is using TDD to well defined methods, like the sum(a,b), it is very useful, but when this method will receive instances or use instance from another integrated services, the mocks receive the greather part of attemption, not the "method objective".

Imagine this service/method to test:

class ClientService:

    def ok_here_is_the_discount(self, some_args):
        # Ok, receive the discount to thi signature, now is possible
        # calcula the it, and response to the broker
        
        self.calculate_user_discount_based_on_signature_type(some_args.discount_value)

    def calculate_user_discount_based_on_signature_type(self, some_args):
        
       # here will send the "result" to the broker
       some_message_borker_publisher(
           some_args.value - some_args.discount_signature
       )

    def request_the_signature_type_discount_in_another_service(self, some_args):
        # Ok, I receive the client that has the signature type,
        # now is need request what is the value to this signature 
        # in signature service

        some_message_borker_publisher(
           queue='siganture.service.what_discount_for_this_signature',
           signature_type=some_args.client.singature_type
        ) 
        #Ok, this message goes to the broker, and the signature.service receive it

    def method_that_receive_messages(self, some_args):

        # Here we receives that want to calculate discount
        # but just receive the client(dict/class/instance) with the signature type,
        # we still dont know the value of theses discount, because when is responsible
        # to manage the siganture, is the signature server

        if some_args.message_type == 'please_calculate_discount':
            self.request_the_signature_type_discount_in_another_service(some_args.client)

        if some_args.message_type == 'message_from_signature_discount':
            self.ok_here_is_the_discount(some_args.value)

    
        

1 - it receive a message 'please_calculate_discount' and call the method

self.request_the_signature_type_discount_in_another_service(some_args.client)

But it still not have the discount value, because this is signature service. (message to the broker)

2 - The supose that the signature server response to 'message_from_signature_discount', then it call the method:

self.ok_here_is_the_discount(some_args.value)

3 - ok, the method ok_here_is_the_discount receive discount and call method

calculate_user_discount_based_on_signature_type()

That now has the values to calculate to the discount and send these value to the broker.

Understand the complexity of these tests (TDD)? I need tests the "method_that_receive_messages" mocking all related nexted actions, or just test the related method, like "calculate_user_discount_based_on_signature_type"?

In this case is better uses a really broker to be possible test it?


Solution

  • Well it is easy to mock things in Python but it still comes with some overhead of course. What I have tended towards over many years now is to set up integration tests with mocks that tests the happy path through the system and then design the system with side effect free functions as much as possible and throw unit tests at them. Then you can start your TDDing with setting up the overall test for the happy path and then unit test particulars in easy to test functions.

    It is still useless when the thing behind the mock changes though but it gives a great sense of security when refactoring.

    The mock libraries in Python are fine but sometimes it is easier to just write your own and replace the real thing with patch. Pretty sweet actually.