Repository: uber-go/zap
File: writer_test.go (Go)

Code before:
		},
		{
			msg:          "file url with fragment",
			paths:        []string{"file://localhost" + tempName + "#foo"},
			wantOtherErr: "fragments not allowed",
		},
		{
			msg:          "file url with query",
			paths:        []string{"file://localhost" + tempName + "?foo=bar"},
			wantOtherErr: "query parameters not allowed",
		},
		{
			msg:          "file with port",
			paths:        []string{"file://localhost:8080" + tempName},
			wantOtherErr: "ports not allowed",
		},
	}

	for _, tt := range tests {
		t.Run(tt.msg, func(t *testing.T) {
			_, cleanup, err := Open(tt.paths...)
			if err == nil {
				defer cleanup()
			}

			if len(tt.wantNotFoundPaths) == 0 && tt.wantOtherErr == "" {
				assert.NoError(t, err, "Unexpected error opening paths %v.", tt.paths)
				return
			}

			require.Error(t, err)
			if len(tt.wantNotFoundPaths) > 0 {
				errs := multierr.Errors(err)
				require.Len(t, errs, len(tt.wantNotFoundPaths))
				for i, err := range errs {
					assert.ErrorIs(t, err, fs.ErrNotExist)
					assert.Contains(t, err.Error(), tt.wantNotFoundPaths[i], "missing path in error")
				}
			}

			if tt.wantOtherErr != "" {
				msg := err.Error()
				assert.Contains(t, msg, tt.wantOtherErr, "Unexpected error opening paths %v.", tt.paths)
			}
		})
	}

	assert.True(t, fileExists(tempName))
	os.Remove(tempName)
}


Review comment (suggestion):
optional: These are three nearly exclusive code paths.
We can use a switch here.

```
switch {
case len(tt.wantNotFoundPaths) > 0:
  // ..

case len(tt.wantOtherErr) > 0:
  // ...

default:
  assert.NoError(t, err, ...)
}
```

Alternatively, given that the shared code is just a couple lines, we can also separate these into two or three separate test functions: success, not-found-paths, and other-errors.

Code after:
		},
		{
			msg:               "missing file scheme url with host localhost",
			paths:             []string{"file://localhost/foo/bar/baz"},
			wantNotFoundPaths: []string{"/foo/bar/baz"},
		},
		{
			msg:   "multiple paths",
			paths: []string{"stdout", "/foo/bar/baz", tempName, "file:///baz/quux"},
			wantNotFoundPaths: []string{
				"/foo/bar/baz",
				"/baz/quux",
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.msg, func(t *testing.T) {
			_, cleanup, err := Open(tt.paths...)
			if !assert.Error(t, err, "Open must fail.") {
				cleanup()
				return
			}

			errs := multierr.Errors(err)
			require.Len(t, errs, len(tt.wantNotFoundPaths))
			for i, err := range errs {
				assert.ErrorIs(t, err, fs.ErrNotExist)
				assert.ErrorContains(t, err, tt.wantNotFoundPaths[i], "missing path in error")
			}
		})
	}
}

func TestOpenRelativePath(t *testing.T) {
	const name = "test-relative-path.txt"

	require.False(t, fileExists(name), "Test file already exists.")
	s, cleanup, err := Open(name)
	require.NoError(t, err, "Open failed.")
	defer func() {
		err := os.Remove(name)
		if !t.Failed() {
			// If the test has already failed, we probably didn't create this file.
			require.NoError(t, err, "Deleting test file failed.")
		}
	}()
	defer cleanup()

	_, err = s.Write([]byte("test"))
	assert.NoError(t, err, "Write failed.")