Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 5 additions & 16 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Go

on:
push:
branches: [ "master" ]
branches: [ "main" ]
pull_request:
branches: [ "master" ]
branches: [ "main" ]

jobs:

Expand All @@ -21,19 +21,8 @@ jobs:
- name: Build
run: go build -v ./...

- name: Set up gomock
run: go install go.uber.org/mock/mockgen@latest

- name: Test
run: go test -v ./...

end-to-end-tests:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.24'

- name: Run End-to-End Tests
run: go test -v -run TestEndToEnd
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.22'
go-version: '1.24'

- name: Build binaries
run: |
Expand Down
35 changes: 33 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,33 @@
# fixturec
Tool for generate test fixtures in golang
# Fixturec

`fixturec` is a command-line utility that automatically generates test fixtures and mocks for Go structs.

🚀 Installation
```
go install github.com/Vypolor/fixturec@latest
```

🧠 How It Works

In the Go file containing your struct, add a go:generate directive:

```
// go:generate fixturec -t Impl
```


where Impl is the name of the struct for which you want to generate a fixture.

The tool performs the following steps:
- analyzes the specified struct and finds fields that are interfaces defined within the same module;
- checks for a //go:generate mockgen ... directive in the interface’s file and adds it if missing;
- runs go generate to create mocks using mockgen;
- generates a fixture_test.go file in the same package as the original struct.

⚙️ Flags

| Flag | Description |
|------|------------------------------------------------------------------------------------------------------|
| `-t` | **(required)** — name of the struct to generate the fixture for. Example: `-t Impl`. |
| `-g` | *(planned)* — disables automatic mock generation. Enabled by default. Currently **not implemented**. |
| `-e` | *(planned)* — enables mock generation for **external packages**. Currently **not implemented**. |
51 changes: 51 additions & 0 deletions internal/generator/fixture/generator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package fixture

import (
"os"
"path/filepath"
"testing"

"github.com/Vypolor/fixturec/internal/generator/dto"
"github.com/stretchr/testify/require"
)

func TestGenerateFixtureFile(t *testing.T) {
t.Parallel()

pkgName := "gen"
structName := "ToGen"

dir, err := os.MkdirTemp("", "fixturec")
if err != nil {
t.Fatal(err)
}

fields := []dto.FieldInfo{
{
FieldName: "myType1",
TypeName: "github.com/Vypolor/without_external/mypackage1.MyType1",
PkgPath: "github.com/Vypolor/without_external/mypackage1",
},
{
FieldName: "myType2",
TypeName: "github.com/Vypolor/without_external/mypackage2.MyType2",
PkgPath: "github.com/Vypolor/without_external/mypackage2",
},
}

require.NoError(t, GenerateFixtureFile(dir, pkgName, structName, fields))

// read golden file
golden, err := os.ReadFile(filepath.Join("testdata", "gen.golden"))
require.NoError(t, err)

// read generated file
genFilePath := filepath.Join(dir, "fixture_test.go")
generated, err := os.ReadFile(genFilePath)
require.NoError(t, err)

require.Equal(t, golden, generated)

// delete temp dir
require.NoError(t, os.RemoveAll(dir))
}
41 changes: 41 additions & 0 deletions internal/generator/fixture/testdata/gen.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package gen

import (
"context"
"testing"

mypackage1_mock "github.com/Vypolor/without_external/mypackage1/mock"
mypackage2_mock "github.com/Vypolor/without_external/mypackage2/mock"
ctrl_mock "go.uber.org/mock/gomock"
)

type fixture struct {
ctrl *ctrl_mock.Controller
ctx context.Context

myType1 *mypackage1_mock.MockMyType1
myType2 *mypackage2_mock.MockMyType2

toGen *ToGen
}

func setUp(t *testing.T) *fixture {
f := &fixture{
ctrl: ctrl_mock.NewController(t),
ctx: context.Background(),

myType1: mypackage1_mock.NewMockMyType1(ctrl_mock.NewController(t)),
myType2: mypackage2_mock.NewMockMyType2(ctrl_mock.NewController(t)),
}

f.toGen = &ToGen{
myType1: f.myType1,
myType2: f.myType2,
}

return f
}

func (f *fixture) tearDown() {
f.ctrl.Finish()
}
Empty file.
Empty file.
5 changes: 4 additions & 1 deletion internal/generator/mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ func GenerateMocks(pkgDir string, fields []dto.FieldInfo) error {
}
dirLine := fmt.Sprintf("//go:generate mockgen -destination=mock/mock_gen.go -package=mock -source=./%s\n",
filepath.Base(filename))
_ = os.WriteFile(filename, append([]byte(dirLine), b...), utils.FilePerm0644)

if err = os.WriteFile(filename, append([]byte(dirLine), b...), utils.FilePerm0644); err != nil {
return fmt.Errorf("failed to write file %s: %w", filename, err)
}
fmt.Printf("Inserted mockgen directive into %s\n", filename)
}

Expand Down