News for hackers. Stuff that matters.
Re:Coverage is not strongly correlated with test suite effec... by Supermancho on Monday September 27, 2021 @11:29PM (#28679000)
In my experience, when a function has more than 1 if statement, it's probably hard to test and you might want to split it up.

When a function has has more than 2 if statements, you definitely want to break it up.

Imagine the function where conditions aren't related at all, as you posited:

    myfn(int x, int y, string foo) {
        if(foo == "bar") {
            do_stuff();
        }
  
        if( x < y ) {
            do_other_stuff();
        }
  
        if(time() == "noon") {
            do_other_other_stuff();
        }
    }
What's really happening here? Why is all this wrapped in 1 function, when the args aren't related at all, nor the work they are dependent on?

Let's say the caller was doing: myfn(1,2,foo);

I would split this function into 3 different function calls in the caller...

    possiblyDoStuff(foo);
    possiblyDoOtherStuff(1,2);
    possiblyDoOtherOtherStuff(time());
Let's use something that you wouldn't simply refactor upstream:

    myfn(string go, string for, string foo) {
        if(go == foo) {
            do_stuff();
        }
  
        if(for == go) {
            do_other_stuff();
        }
  
        if(foo == for) {
            do_other_other_stuff();
        }

        someOtherFn(go, for, foo);
    }
Move that complexity into smaller chunks:

    myfn(string go, string for, string foo) {
        possiblyDoStuff(go, foo);
        possiblyDoOtherStuff(go, for);
        possiblyDoOtherOtherStuff(for, foo);
        someOtherFn(go, for, foo);
    }
Now you have the 7 tests. 2 for each possibly = 6 which are pretty easy and 1 for myfn. It is exceedingly rare that functions require this kind of attention. There are usually a bunch of side effects or return values that are dependent on these checks. eg:

    myfn(string go, string for, string foo) {
        // examples of why you are calling these, to get vals
        var go2 = possiblyDoStuff(go, foo);
        var for2 = possiblyDoOtherStuff(go, for);
        var foo2 = possiblyDoOtherOtherStuff(for, foo);
        return { go2, for2, foo2 };

        //move this to caller someOtherFn(myfn(go, for, foo));
    }

There are no comments on this comment yet.