# More unit testing with Excel Lambdas revisited

27 Apr 2022Like all programming there are many ways to solve any problem and I saw a comment that had a pretty neat, more Excelesque way (I think - I’m not an Excel user) of solving the problem. To drive home the benefit of testing this post adds a couple of tests to the current approach, then I’ll rewrite the solution entirely but keep the tests the same. If all goes well the formula will be completely different but my level of confidence in the calculation will still be high as it satisfies my assumptions that I encoded in some tests.

## Let’s add some tests

For a post that was about testing I shockingly didn’t test the final formula 🤦🏼♂️, which currently looks like this

```
=Pair.First(REDUCE(PairMake(0,Data!A1),Data!A1:Data!A2000,NextPartialResult))
```

The `PairMake`

function and `NextPartialResult`

function had tests written but the whole thing did not.
Therefore it’s not safe for me to just change the above formula until I get it behind some tests.

For testing this I’m going to use my current data set and pick different slices of it to produce different results from the formula:

A (Formula) | A (Result) | B | C (Formula) | C (Result) | D | E | F | |
---|---|---|---|---|---|---|---|---|

1 | Actual | Actual | Expected | Result | Result | Result Text | 199 | |

2 | `=SolveTask1(F1:F10)` |
7 | 7 | `=Assert.Equals(B2,C2)` |
✅ | 200 | ||

3 | `=SolveTask1(F8:F10)` |
1 | 1 | `=Assert.Equals(B3,C3)` |
✅ | 208 | ||

4 | `=SolveTask1(F3:F10)` |
5 | 5 | `=Assert.Equals(B4,C4)` |
✅ | 210 | ||

5 | 200 | |||||||

6 | 207 | |||||||

7 | 240 | |||||||

8 | 269 | |||||||

9 | 260 | |||||||

10 | 263 |

With the above I can massage my original solution into a named function called `SolveTask1`

(naming is hard) that will make all the above tests pass.

```
SolveTask1 = LAMBDA(range,
Pair.First(REDUCE(PairMake(0,OFFSET(range,0,0,1)),range,NextPartialResult))
);
```

## Throw everything away and write again

With these tests in place I have a level of confidence that if I call `SolveTask1`

then it should behave as long as I keep the same tests.
The solution I’m going to implement (there could be many more) is based on a comment from `twobitshifter`

who suggested `={SUM(—-(A1:A1999<A2:2000)}`

.

If I rejig the suggested formula to work in a named function I come up with the following that also passes my tests

```
SolveTask1 = LAMBDA(range,
SUM(--(OFFSET(range,0,0,ROWS(range) - 1)<OFFSET(range,1,0,ROWS(range) - 1)))
);
```

This is a real improvement as I’ve got my final calculation behind some tests that gives me confidence.
It also means I can delete all the old tests from my previous post and remove the `NextPartialResult`

helper function entirely - throwing code away is a good thing as less code = less bugs.

Of course we don’t have to stop right there, I might look at the solution above and not be happy about the duplication of `ROWS(range) - 1`

.
Because this is all tested I can very quickly introduce a `LET`

and as all of my tests still pass I know I didn’t fudge something up whilst making the change.

```
SolveTask1 = LAMBDA(range,
LET(
sliceSize, ROWS(range) - 1,
SUM(--(OFFSET(range,0,0,sliceSize)<OFFSET(range,1,0,sliceSize)))
)
);
```

## Conclusion

I was able to take a working formula and change it a few times without worrying if I was going to break anything. The first change was a complete rewrite and change of approach and the second change was more of an iterative improvement. Having the tests present gave me the confidence to make broad changes without needing to go and do a load of manual verification or to spend forever statically analysing the code to guess that it still works.