Testing code that uses the os and ioutil packages is tricky. I created
  https://pkg.go.dev/github.com/twpayne/go-vfs
  https://pkg.go.dev/github.com/twpayne/go-vfs/vfst
to make it easier.

Key features:
- Everything eventually calls the underlying os/ioutil function, so you get 
real behavior, not fake (and possibly incorrect) mock behavior.
- Makes it really easy to create, populate, and tear down temporary 
directories for hermetic tests.

It's best demonstrated by example:
  
https://pkg.go.dev/github.com/twpayne/go-vfs/vfst?tab=doc#example-NewTestFS

Using vfs.FS you can create instances that fail in whatever way you want, 
for example:


package main

import (
"os"
"testing"

"github.com/twpayne/go-vfs"
"github.com/twpayne/go-vfs/vfst"
)

// a readDirFailer wraps a vfs.FS but all calls to ReadDir fail with
// os.ErrPermission.
type readDirFailer struct {
vfs.FS
}

func (readDirFailer) ReadDir(dirname string) ([]os.FileInfo, error) {
return nil, os.ErrPermission
}

// testReadDirFailer tests that calling fs.ReadDir returns an error.
func testReadDirFailer(t *testing.T, fs vfs.FS) {
if _, err := fs.ReadDir("/"); err == nil {
t.Errorf("expected error from ReadDir")
}
}

func TestX(t *testing.T) {
fs, cleanup, err := vfst.NewTestFS(nil)
if err != nil {
t.Fatal(err)
}
defer cleanup()

testReadDirFailer(t, readDirFailer{FS: fs})
}


HTH,
Tom

On Saturday, April 11, 2020 at 12:16:30 AM UTC+1, Ian Lance Taylor wrote:
>
> On Fri, Apr 10, 2020 at 3:37 PM 'K Richard Pixley' via golang-nuts 
> <golan...@googlegroups.com <javascript:>> wrote: 
> > 
> > I have some code.  It uses ioutil.ReadDir which returns a possible 
> error. 
> > 
> > My testing is at 99% code coverage because I can't figure out a way to 
> > set up a situation in which os.Open succeeds on a directory, but 
> > ioutil.ReadDir fails. 
> > 
> > I can get to 100% code coverage if I throw away the err rather than 
> > testing for it and reporting it but that seems a bit... well... 
> > disingenuous.  I've looked down the calls to the kernel call 
> > getdirentries but the only errno I can see being relevant to a go 
> > program is EIO and I can't think of a way to force that to happen on a 
> > real file system. 
> > 
> > I can imagine a fake file system created specifically for this purpose, 
> > but that seems an awfully long way around the barn. 
> > 
> > How can I get to 100% code coverage?  Or should I just give up on 
> > finding a way to cover that last, single line of error handling code? 
>
> I'm not proud.  Here is an example program for which os.Open(dirname) 
> succeeds but ioutil.ReadDir(dirname) fails.  You may have to adjust 
> pathMax and nameMax for your system.  Whether you actually want to use 
> this technique is left to you. 
>
> Ian 
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/0a3d1ff3-2dcb-4c75-afb5-041db4d5a435%40googlegroups.com.

Reply via email to