Skip to content
This repository was archived by the owner on Sep 3, 2025. It is now read-only.

Conversation

@derrickstolee
Copy link
Collaborator

@derrickstolee derrickstolee commented Jan 31, 2023

I set out to learn more about Go and the unit testing framework that @vdye set up in github/git-fundamentals#9, with a focus on picking a very simple method from our core package: GetRepositories().

Along the way, @vdye helped me find a way to move a significant portion of shared_test.go into another place that can be reused in multiple places. Specifically, we will need the mocked structures. I use MockFileSystem in this PR, and had to extend it for the filesystem methods used in GetRepositories().

Important things to note:

  1. In order to "export" things across packages, the type and method names must start with a capital letter. They must also not be in a file ending with _test.go.
  2. We can avoid using a package name in every instance of a type using . "<package>" in the import statement. This avoids an even worse transformation in the existing tests, which are already converting many lowercase types and methods into uppercase.

Hopefully this large change to take the core of our unit-testing strategy and make it accessible to other packages will be relatively stable in future iterations. Then, we can hopefully result in more involved unit tests in the future that test things like the bundling strategy.

@derrickstolee derrickstolee self-assigned this Jan 31, 2023
Copy link
Collaborator

@vdye vdye left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These test updates and reorganization (and bugfix!) help us move towards a better overall framework for the bundle server, thanks for doing this! My comments are mainly around ways the changes can be simplified/take advantage of existing infrastructure - hopefully not too invasive.

@derrickstolee derrickstolee force-pushed the stolee/bundle-create-tests branch from 423a227 to 8813035 Compare January 31, 2023 20:01
In an effort to make the codebase more unit-testable, we need to be able
to mock certain lower layers of the system. We already have a FileSystem
interface for interacting with the filesystem, but it is not yet robust
enough for us to parse an existing file, as needed for
GetRepositories().

Add a new ReadFileLines() method that takes a filename and returns a
string slice (or error) and adapt GetRepositories() to use it. Note that
this abstracts both os.OpenFile() and bufio.NewReader(). This should
simplify the interface for most content interaction, but also will
simplify the mocks we will eventually create for this method.

Adjust all callers of GetRepositories() to provide a FileSystem,
specifically the "real" one for now, until we can replace enough items
with mockable interfaces that those methods can use an injected
dependency at the command level.

Helped-by: Victoria Dye <[email protected]>
Signed-off-by: Derrick Stolee <[email protected]>
Continuing our efforts to make our code unit testable, add a user.User
struct to the parameters for the methods in paths.go. This allows us to
remove the rest of the dependencies on the real system in the
GetRepositories() method. It requires some more work elsewhere in the
codebase for all the places where the path methods are used.

Signed-off-by: Derrick Stolee <[email protected]>
The shared_test namespace as added in 92237dd (systemd: implement
'Create()' function, 2023-01-10) and a4d43a6 (launchd: implement
'Create()' function, 2023-01-10) are helpful for unit testing logic.
However, there are multiple barriers from using this mocking
infrastructure in other tests, such as in internal/common:

 1. The 'shared_test' namespace does not allow sharing anything
    beyond the internal/daemon/ directory. Moving it into just
    internal/ does not seem to make this visible. The "_test"
    portion of the package tells Go to treat it with special
    properties.

 2. After moving the definitions into internal/commontest/, the
    definitions are not visible to anyone else because all the names
    start with a lowercase letter. Convert these to uppercase so they
    will be visible.

 3. By extracting to an external package, we suddenly would need to add
    "commontest." in front of all of the imported terms. Use a trick in
    the import statement ('. "package"') to allow skipping this prefix.

Signed-off-by: Derrick Stolee <[email protected]>
Create a unit test setup for the GetRepositories() method, to ensure
that it works correctly with mocks.

For this method, we only need to mock FileSystem.ReadFileLines() once,
so we can have our tests store exactly one list of lines.

Create a fake user.User struct to provide the HomeDir value.

The only test implemented right now is the empty file.

Signed-off-by: Derrick Stolee <[email protected]>
Add a few more cases to TestRepos_GetRepositories() including an error
from the filesystem, a single repo case, and multiple repositories.

Be sure to match the expected output of ReadFileLines() which is to trim
the newlines.

In the multiple repositories case, I added an empty line to check the
case of skipping newlines. In an earlier version of this commit, I had
thought there was a bug, but it was due to me including newlines in the
mocked output.

Signed-off-by: Derrick Stolee <[email protected]>
Copy link
Collaborator

@vdye vdye left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updates look good, and everything seems to have rebased without introducing issues. Nice work!

@derrickstolee derrickstolee merged commit d70a1b1 into main Feb 1, 2023
@vdye vdye deleted the stolee/bundle-create-tests branch May 3, 2023 17:51
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants