mercredi 25 novembre 2015

How to simulate an external event during testing at a particular point in code

I am trying to work out the best way to simulate something bad happening at very specific points during the execution of code I’m testing, to make sure the code which is supposed to recover from the "bad thing" actually works as expected.

In my particular case I want to simulate a user making detrimental changes to various files, but really any arbitrary example you could think of would apply.

The simplest way I can think of to do this is to make calls to an empty “stub” method which would do nothing at all in production, but which I will mock out during testing with a patch to do the actual work of making the bad thing happen. In my example the patch would rename or delete files which were being operated on by the script.

Consider the following generic example which is in Python but could be written in any language you'd like:

script.py:

def simulate_bad_thing_during_testing():
    # This is an intentionally empty stub to be mocked out during testing.
    pass

def main():
    # Do some work.
    ...

    simulate_bad_thing_during_testing()

    # Do some more work, even if bad thing has happened.
    ...

test_script.py:

def do_bad_thing():
    # Do the bad thing here.
    ...

@mock.patch('simulate_bad_thing_during_testing', side_effect=do_bad_thing)
def test_main_recovers_from_bad_thing():
    main()

    # assert all was well and the script recovered from the bad thing.
    ...

Is this way of doing it common practice? I've been trying to find examples of this on the net and have failed.

If others have done it before, then what is it called? Perhaps my Google-fu would be better if I had a better term for this. I've come across "mutation" testing and "fuzz" testing, but both of those terms seem to denote something different.

Is there a better way to simulate arbitrary worst-case scenarios at particular points in code under test? Perhaps one that won't raise the eyebrows of teammates wondering why I've chosen such an "invasive" way of doing this. I do feel slightly uncomfortable with such tight coupling between the implementation of my function and the tests covering the function, but how else can I "hook" into a particular line in this fashion?

Aucun commentaire:

Enregistrer un commentaire