Up to Main Index                           Up to Journal for October, 2018

                     JOURNAL FOR MONDAY 8TH OCTOBER, 2018
______________________________________________________________________________

SUBJECT: More updates + A testing light bulb moment
   DATE: Mon  8 Oct 20:45:25 BST 2018

October already? Not long till Halloween :) I’ve been looking at the changes
on the public dev branch to see if there are enough to justify my usual
Halloween release. I think there is. The last release was in July, so it’s
about time all of the new changes were rolled up and rolled out.

Public dev branch has just been updated with some more fixes and updates.

Decoding a Duration now rounds (half up) to the nearest second. Otherwise
decoding and encoding a duration could produce different results.

Decoding a DateTime now strips leading/trailing white space.

The tests for encoding and decoding Bytes have been cleaned up. I’ve actually
separated the tests into two functions: TestBytes and TestBytesSideEfects.
Originally I was trying to test the result of calling Bytes and test for side
effects from the call — such as the passed parameter being modified and making
sure a copy was being returned. This proved to be a mistake as it made the
tests overly complicated.

In the tests for Bytes I wanted to make sure that a copy of the data was
returned and not a re-slicing of the passed slice. So I used a technique I’d
seen before and compared the addresses of the last possible element in each
slice:


  haveEnd := &have[0:cap(have)][cap(have)-1]
  wantEnd := &want[0:cap(want)][cap(want)-1]
  if haveEnd == wantEnd {
    t.Errorf("have and want overlap: %+q", have)
  }


However, with the introduction of full indexing expressions, this is no longer
a viable solution — as the cap for a slice can now be changed. Although I did
notice in Go 1.11.1 it’s still used in the alias function in math/big/nat.go.
I’m guessing as the function is not exported the slices are controlled and
full indexing is known not to be used or an issue?

I went on a long hunt for another solution. I tried various options using the
reflect and unsafe packages, nothing worked and the code was becoming more
convoluted.

I finally came to my senses, which was when I split up the main tests from the
tests for side effects. It was also when I realised there was an easy way to
test if the result returned from Bytes overlapped with the original array — I
simply overwrote the results! To start with, I manually created a backing
array so I had access to it. Then I sliced it to create my parameter for
Bytes. The result of calling Bytes was then overwritten. If the backing array
changed due to the overwriting then the resulting slice was not a copy.

I had a similar situation with the decode.DateTime tests. I needed to add
tests for trying to parse invalid date/time strings. Initially I tried
shoehorning the additional checking into the TestDateTime function. That
turned into another convoluted mess. Again I split the additional tests out
into a separate test function — TestDateTimeInvalid.

I don’t know where I got the notion of one testing function per function being
tested came from initially? Having multiple, very specific test functions
hitting a function under test in different ways keeps the tests very simple.

Don’t you just love it when you have those sudden moments of clarity? In
hindsight it’s obvious really. We break complex code down into multiple
functions, each with a specific purpose. So why not apply it to writing tests
as well?

I’ll have to look at my other tests and see which ones could benefit from
being split up and improved.

--
Diddymus


  Up to Main Index                           Up to Journal for October, 2018