Skip to main content
Question Protected by gnat
Tweeted twitter.com/#!/StackProgrammer/status/343549924765466624
Clarifications
Source Link
acjay
  • 346
  • 2
  • 12

I'm really struggling to write effective unit tests for a large Django project. I have reasonably good test coverage, but I've come to realize that the tests I've been writing are definitely integration/acceptance tests, not unit tests at all, and I have critical portions of my application that are not being tested effectively. I want to fix this ASAP.

Here's my problem. My schema is deeply relational, and heavily time-oriented, giving my model object high internal coupling and lots of state. Many of my model methods query based on time intervals, and I've got a lot of auto_now_add going on in timestamped fields. So take a method that looks like this for example:

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()
    
    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.methodkey_method(startTime, endTime) for object in objects)

How does one approach testing something like this?

Here's where I am so far. It occurs to me that the unit testing objective should be given some mocked behavior by key_method on its arguments, is summary correctly filtering/aggregating to produce a correct result?

Mocking datetime.now() is straightforward enough, but how can I mock out the rest of the behavior?

  • Mocking datetime.now() is straightforward enoughI could use fixtures, but how can I unit test the rest of the functionality? I'veI've heard pros and cons of using fixtures for building my data (poor maintainability being a con that hits home for me).
  • I could also setup my data through the ORM, but that can be limiting as well, because then I have to create related objects as well. And the ORM doesn't let you mess with auto_now_add fields manually.
  • Mocking the ORM is another option, but not only is it tricky to mock deeply nested ORM methods, but the logic in the ORM code gets mocked out of the test, and mocking seems to make the test really dependent on the internals and dependencies of the function-under-test.

The toughest nuts to crack seem to be the functions like this, that sit on a few layers of models and lower-level functions and are very dependent on the time, even though these functions may not be super complicated. My overall problem is that no matter how I seem to slice it, my tests are looking way more complex than the functions they are testing. I think I've gone off-track someplace, because I don't think it should be like that. Perhaps my function should be broken into smaller chunks, but it's not that big to begin with, and I don't want to end up with ravioli.

I'm really struggling to write effective unit tests for a large Django project. I have reasonably good test coverage, but I've come to realize that the tests I've been writing are definitely integration/acceptance tests, not unit tests at all, and I have critical portions of my application that are not being tested effectively. I want to fix this ASAP.

Here's my problem. My schema is deeply relational, and heavily time-oriented. Many of my model methods query based on time intervals, and I've got a lot of auto_now_add going on in timestamped fields. So take a method that looks like this for example:

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()
    
    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.method() for object in objects)

How does one approach testing something like this?

  • Mocking datetime.now() is straightforward enough, but how can I unit test the rest of the functionality? I've heard pros and cons of using fixtures for building my data (poor maintainability being a con that hits home for me).
  • I could also setup my data through the ORM, but that can be limiting as well, because then I have to create related objects as well. And the ORM doesn't let you mess with auto_now_add fields manually.
  • Mocking the ORM is another option, but not only is it tricky to mock deeply nested ORM methods, but the logic in the ORM code gets mocked out of the test, and mocking seems to make the test really dependent on the internals and dependencies of the function-under-test.

The toughest nuts to crack seem to be the functions that sit on a few layers of models and lower-level functions and are very dependent on the time, even though these functions may not be super complicated. My overall problem is that no matter how I seem to slice it, my tests are looking way more complex than the functions they are testing. I think I've gone off-track someplace, because I don't think it should be like that. Perhaps my function should be broken into smaller chunks, but it's not that big to begin with, and I don't want to end up with ravioli.

I'm really struggling to write effective unit tests for a large Django project. I have reasonably good test coverage, but I've come to realize that the tests I've been writing are definitely integration/acceptance tests, not unit tests at all, and I have critical portions of my application that are not being tested effectively. I want to fix this ASAP.

Here's my problem. My schema is deeply relational, and heavily time-oriented, giving my model object high internal coupling and lots of state. Many of my model methods query based on time intervals, and I've got a lot of auto_now_add going on in timestamped fields. So take a method that looks like this for example:

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()
    
    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.key_method(startTime, endTime) for object in objects)

How does one approach testing something like this?

Here's where I am so far. It occurs to me that the unit testing objective should be given some mocked behavior by key_method on its arguments, is summary correctly filtering/aggregating to produce a correct result?

Mocking datetime.now() is straightforward enough, but how can I mock out the rest of the behavior?

  • I could use fixtures, but I've heard pros and cons of using fixtures for building my data (poor maintainability being a con that hits home for me).
  • I could also setup my data through the ORM, but that can be limiting, because then I have to create related objects as well. And the ORM doesn't let you mess with auto_now_add fields manually.
  • Mocking the ORM is another option, but not only is it tricky to mock deeply nested ORM methods, but the logic in the ORM code gets mocked out of the test, and mocking seems to make the test really dependent on the internals and dependencies of the function-under-test.

The toughest nuts to crack seem to be the functions like this, that sit on a few layers of models and lower-level functions and are very dependent on the time, even though these functions may not be super complicated. My overall problem is that no matter how I seem to slice it, my tests are looking way more complex than the functions they are testing.

Clarifications
Source Link
acjay
  • 346
  • 2
  • 12

I'm really struggling to write effective unit tests for a large Django project. I have reasonably good test coverage, but I've come to realize that the tests I've been writing are definitely integration/acceptance tests, not unit tests at all, and I have critical portions of my application that are not being tested effectively. I want to fix this ASAP.

Here's my problem. My schema is deeply relational, and heavily time-oriented. Many of my model methods query based on time intervals, and I've got a lot of auto_now_add going on in timestamped fields. So take a method that looks like this for example:

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()
    
    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.method() for object in objects)

How does one approach testing something like this?

Mocking datetime.now() is straightforward enough, but how can I unit test the rest of the functionality? I've heard pros and cons of using fixtures for building my data (poor maintainability being a con that hits home for me). I could also setup my data through the ORM, but that can be limiting as well, because then I have to create related objects as well. Mocking is another option, but not only is it tricky to mock deeply nested ORM methods, but the logic in the ORM code gets mocked out of the test, it seems to make the test really dependent on the internals and dependencies of the function-under-test. Perhaps my function should be broken into smaller chunks, but it's not that big to begin with, and I don't want to end up with ravioli.

  • Mocking datetime.now() is straightforward enough, but how can I unit test the rest of the functionality? I've heard pros and cons of using fixtures for building my data (poor maintainability being a con that hits home for me).
  • I could also setup my data through the ORM, but that can be limiting as well, because then I have to create related objects as well. And the ORM doesn't let you mess with auto_now_add fields manually.
  • Mocking the ORM is another option, but not only is it tricky to mock deeply nested ORM methods, but the logic in the ORM code gets mocked out of the test, and mocking seems to make the test really dependent on the internals and dependencies of the function-under-test.

The toughest nuts to crack seem to be the functions that sit on a few layers of models and lower-level functions and are very dependent on the time, even though these functions may not be super complicated. My overall problem is that no matter how I seem to slice it, my tests are looking way more complex than the functions they are testing. I think I've gone off-track someplace, because I don't think it should be like that. Perhaps my function should be broken into smaller chunks, but it's not that big to begin with, and I don't want to end up with ravioli.

I'm really struggling to write effective unit tests for a large Django project. I have reasonably good test coverage, but I've come to realize that the tests I've been writing are definitely integration/acceptance tests, not unit tests at all, and I have critical portions of my application that are not being tested effectively. I want to fix this ASAP.

Here's my problem. My schema is deeply relational, and heavily time-oriented. Many of my model methods query based on time intervals, and I've got a lot of auto_now_add going on in timestamped fields. So take a method that looks like this for example:

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()
    
    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.method() for object in objects)

How does one approach testing something like this?

Mocking datetime.now() is straightforward enough, but how can I unit test the rest of the functionality? I've heard pros and cons of using fixtures for building my data (poor maintainability being a con that hits home for me). I could also setup my data through the ORM, but that can be limiting as well, because then I have to create related objects as well. Mocking is another option, but not only is it tricky to mock deeply nested ORM methods, but the logic in the ORM code gets mocked out of the test, it seems to make the test really dependent on the internals and dependencies of the function-under-test. Perhaps my function should be broken into smaller chunks, but it's not that big to begin with, and I don't want to end up with ravioli.

The toughest nuts to crack seem to be the functions that sit on a few layers of models and lower-level functions and are very dependent on the time, even though these functions may not be super complicated. My overall problem is that no matter how I seem to slice it, my tests are looking way more complex than the functions they are testing. I think I've gone off-track someplace, because I don't think it should be like that.

I'm really struggling to write effective unit tests for a large Django project. I have reasonably good test coverage, but I've come to realize that the tests I've been writing are definitely integration/acceptance tests, not unit tests at all, and I have critical portions of my application that are not being tested effectively. I want to fix this ASAP.

Here's my problem. My schema is deeply relational, and heavily time-oriented. Many of my model methods query based on time intervals, and I've got a lot of auto_now_add going on in timestamped fields. So take a method that looks like this for example:

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()
    
    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.method() for object in objects)

How does one approach testing something like this?

  • Mocking datetime.now() is straightforward enough, but how can I unit test the rest of the functionality? I've heard pros and cons of using fixtures for building my data (poor maintainability being a con that hits home for me).
  • I could also setup my data through the ORM, but that can be limiting as well, because then I have to create related objects as well. And the ORM doesn't let you mess with auto_now_add fields manually.
  • Mocking the ORM is another option, but not only is it tricky to mock deeply nested ORM methods, but the logic in the ORM code gets mocked out of the test, and mocking seems to make the test really dependent on the internals and dependencies of the function-under-test.

The toughest nuts to crack seem to be the functions that sit on a few layers of models and lower-level functions and are very dependent on the time, even though these functions may not be super complicated. My overall problem is that no matter how I seem to slice it, my tests are looking way more complex than the functions they are testing. I think I've gone off-track someplace, because I don't think it should be like that. Perhaps my function should be broken into smaller chunks, but it's not that big to begin with, and I don't want to end up with ravioli.

added 286 characters in body
Source Link
acjay
  • 346
  • 2
  • 12

I'm really struggling to write effective unit tests for a large Django project. I have reasonably good test coverage, but I've come to realize that the tests I've been writing are definitely integration/acceptance tests, not unit tests at all, and I have critical portions of my application that are not being tested effectively. I want to fix this ASAP.

Here's my problem. My schema is deeply relational, and heavily time-oriented. Many of my model methods query based on time intervals, and I've got a lot of auto_now_add going on in timestamped fields. So take a method that looks like this for example:

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()
    
    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.method() for object in objects)

How does one approach testing something like this?

Mocking datetime.now() is straightforward enough, but how can I unit test the rest of the functionality? I've heard pros and cons of using fixtures for building my data (poor maintainability being a con that hits home for me). I could also setup my data through the ORM, but that can be limiting as well, because then I have to create related objects as well. Mocking is another option, but not only is it tricky to memock deeply nested ORM methods, but the logic in the ORM code gets mocked out of the test, it seems to make the test really dependent on the internals and dependencies of the function-under-test. Perhaps my function should be broken into smaller chunks, but it's not that big to begin with, and I don't want to end up with ravioli.

The toughest nuts to crack seem to be the functions that sit on a few layers of models and lower-level functions and are very dependent on the time, even though these functions aremay not be super complicated. My overall problem is that no matter how I seem to slice it, my tests are looking way more complex than the functions they are testing. I think I've gone off-track someplace, because I don't think it should be like that.

I'm really struggling to write effective unit tests for a large Django project. I have reasonably good test coverage, but I've come to realize that the tests I've been writing are definitely integration/acceptance tests, not unit tests at all, and I have critical portions of my application that are not being tested effectively. I want to fix this ASAP.

Here's my problem. My schema is deeply relational, and heavily time-oriented. Many of my model methods query based on time intervals, and I've got a lot of auto_now_add going on in timestamped fields. So take a method that looks like this for example:

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()
    
    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.method() for object in objects)

How does one approach testing something like this?

Mocking datetime.now() is straightforward enough, but how can I unit test the rest of the functionality? I've heard pros and cons of using fixtures for building my data (poor maintainability being a con that hits home for me). I could also setup my data through the ORM, but that can be limiting as well, because then I have to create related objects as well. Mocking is another option, but to me, it seems to make the test really dependent on the internals and dependencies of the function-under-test.

The toughest nuts to crack seem to be the functions that sit on a few layers of models and lower-level functions, even though these functions are not super complicated. My overall problem is that no matter how I seem to slice it, my tests are looking way more complex than the functions they are testing. I think I've gone off-track someplace, because I don't think it should be like that.

I'm really struggling to write effective unit tests for a large Django project. I have reasonably good test coverage, but I've come to realize that the tests I've been writing are definitely integration/acceptance tests, not unit tests at all, and I have critical portions of my application that are not being tested effectively. I want to fix this ASAP.

Here's my problem. My schema is deeply relational, and heavily time-oriented. Many of my model methods query based on time intervals, and I've got a lot of auto_now_add going on in timestamped fields. So take a method that looks like this for example:

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()
    
    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.method() for object in objects)

How does one approach testing something like this?

Mocking datetime.now() is straightforward enough, but how can I unit test the rest of the functionality? I've heard pros and cons of using fixtures for building my data (poor maintainability being a con that hits home for me). I could also setup my data through the ORM, but that can be limiting as well, because then I have to create related objects as well. Mocking is another option, but not only is it tricky to mock deeply nested ORM methods, but the logic in the ORM code gets mocked out of the test, it seems to make the test really dependent on the internals and dependencies of the function-under-test. Perhaps my function should be broken into smaller chunks, but it's not that big to begin with, and I don't want to end up with ravioli.

The toughest nuts to crack seem to be the functions that sit on a few layers of models and lower-level functions and are very dependent on the time, even though these functions may not be super complicated. My overall problem is that no matter how I seem to slice it, my tests are looking way more complex than the functions they are testing. I think I've gone off-track someplace, because I don't think it should be like that.

Source Link
acjay
  • 346
  • 2
  • 12
Loading