Skip to content

Commit

Permalink
Allow project_root to be specified by relative path (#23)
Browse files Browse the repository at this point in the history
* Feat: can use relative path!

* Fix: README
  • Loading branch information
sanposhiho authored Mar 10, 2021
1 parent cceeda2 commit a359138
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 151 deletions.
88 changes: 60 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@ If you find any bugs or have feature requests, please feel free to create an iss

gomockhandler is handler of [golang/mock](https://github.com/golang/mock), as the name implies.

Some of you may often create mock with `go generate` like below.
```
//go:generate mockgen -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAG
```

But, it will take time to execute `go generate ./...` for projects with many files. And we cannot easily check if mock is up-to-date.

`gomockhandler` use one config file to generate all mocks.

With `gomockhandler`,
Expand All @@ -29,7 +22,17 @@ Here is some example of the mock being generated in half the time with `gomockha
![Screen Shot 2021-03-09 at 12 07 03](https://user-images.githubusercontent.com/44139130/110413121-ac778900-80d0-11eb-89c1-73b7e80c11c9.png)


## Background

Some of you may often manage your mocks with `go generate` like below.

```
//go:generate mockgen -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAG
```

But, it will take long time to execute `go generate ./...` for projects with many files.

And we cannot easily check if mock is up-to-date.

## Install

Expand All @@ -48,34 +51,44 @@ go install github.com/sanposhiho/gomockhandler

## How to use

### [preparation] generate the config file
`gomockhandler` is designed to be simple and does only three things

If you don't use `go:generate` to execute mockgen, see [#Add a new mock to be generated](#add-a-new-mock-to-be-generated).
- generate/edit a config
- generate mock from config
- check if mocks are up-to-date

If you use `go:generate` to execute mockgen, you can generate the config file by rewriting `go:generate` comment a little bit.
## generate/edit a config

replace from `mockgen` to `gomockhandler -project_root=/path/to/project_root`, and run `go generate ./...` in your project.
We need config for `gomockhandler`.
However, you don't need to generate/edit the config directly, it can be generated/edited from the CLI.

### Configuring a new mock

You can configure a new mock to be generated with CLI.

If the config file does not exist in your project root directory, it will be created.

For example, suppose you want to generate the same mock with gomockhandler as the one generated by mockgen below.

```
- //go:generate mockgen -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAG
+ //go:generate gomockhandler -project_root=/path/to/project -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAG
mockgen -source=foo.go -destination=../mock/
```

gomockhandler will generate a config file named `gomockhandler.json` in your project root directory.

After generating the config, your `go:generate` comments are no longer needed. You've been released from a slow-mockgen with `go generate`.
Let's delete `go:generate` comments.
The following commands can be used to configure the settings.
As you can see, we just need to add the option `project_root`.

### Add a new mock to be generated
```
gomockhandler -project_root=/path/to/project -source=foo.go -destination=../mock/
```

You can add a new mock to be generated from CLI. You can use the same options as mockgen to add a new mock. If the config file does not exist in your project root directory, it will be created.
---

You can use all options of mockgen to add a new mock.

`mockgen` has two modes of operation: source and reflect, and, gomockhandler support both.
`mockgen` has two modes of operation: source and reflect, and gomockhandler support both.

See [golang/mock#running-mockgen](https://github.com/golang/mock#running-mockgen) for more information.


Example(Source mode):
```
gomockhandler -project_root=/path/to/project -source=foo.go [other options]
Expand All @@ -86,31 +99,50 @@ Example(Reflect mode):
gomockhandler -project_root=/path/to/project [options] database/sql/driver Conn,Driver
```

### [WIP]Edit/Delete mocks
### [optional] generate the config file from go generate comments

If you use `go:generate` to execute mockgen now, you can generate the config file by rewriting `go:generate` comment a little bit.

Currently, if you want to modify/delete the mock, you have to modify the config manually...
replace from `mockgen` to `gomockhandler -project_root=/path/to/project_root`, and run `go generate ./...` in your project.

```
- //go:generate mockgen -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAG
+ //go:generate gomockhandler -project_root=/path/to/project -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAG
```

After generating the config, your `go:generate` comments are no longer needed. You've been released from a slow-mockgen with `go generate`!

Let's delete `go:generate` comments.

### [WIP] Delete mocks

Currently, if you want to delete the mock, you have to modify the config manually...

I'm working on developing it to be able to edit/delete it from the CLI.

### generate mock
## generate mock

You can generate all mocks from config.

You don't have to specify config option, when you are in project root.

```
gomockhandler -config=gomockhandler.json -concurrency=100 mockgen
```

### check if mock is up-to-date
## check if mock is up-to-date

It is useful for ci to check if all mocks are up-to-date

You don't have to specify config option, when you are in project root.

```
gomockhandler -config=gomockhandler.json check
```

You can see the error if some mocks are not up to date.
If some mocks are not up to date, you can see the error and `gomockhandler` will exit with exit-code 1

```
2021/03/06 02:37:16 mock is not up to date. source: user.go, destination: ../mock/user.go
2021/03/10 22:17:12 [WARN] mock is not up to date. source: ./interfaces/user.go, destination: ./interfaces/../mock/user.go
2021/03/10 22:17:12 mocks is not up-to-date
```

4 changes: 2 additions & 2 deletions gomockhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import (
)

var (
projectRoot = flag.String("project_root", "", "(for generate a config) A config file will be generated in project root. You should specify as absolute path")
configPath = flag.String("config", "", "(for mockgen/chack) The path to config file. You can use both absolute path and relative path")
projectRoot = flag.String("project_root", "", "(for generate config) A config file will be generated in project root.")
configPath = flag.String("config", "./gomockhandler.json", "(for mockgen/chack) The path to config file.")
concurrency = flag.Int("concurrency", 1, "Number of processes in parallel.")

// flags for mockgen
Expand Down
5 changes: 0 additions & 5 deletions playground/gomockhandler.json

This file was deleted.

4 changes: 3 additions & 1 deletion playground/interfaces/user.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package interfaces

//go:generate ../../gomockhandler -project_root=/Users/sanposhiho/workspace/gomockhandler/playground -source=$GOFILE -destination=../mock/$GOFILE
// Since this is a playground, the gomockhandler is mentioned in the comment of go generate for testing config generation, but it is not necessary.
// You don't need go generate comments anymore with gomockhandler
//go:generate ../../gomockhandler -project_root=../ -source=$GOFILE -destination=../mock/$GOFILE

type User interface {
String() string
Expand Down
4 changes: 3 additions & 1 deletion playground/interfaces/user2.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package interfaces

//go:generate ../../gomockhandler -project_root=/Users/sanposhiho/workspace/gomockhandler/playground -destination=../mock/$GOFILE . User2
// Since this is a playground, the gomockhandler is mentioned in the comment of go generate for testing config generation, but it is not necessary.
// You don't need go generate comments anymore with gomockhandler
//go:generate ../../gomockhandler -project_root=../ -destination=../mock/$GOFILE . User2

type User2 interface {
String2() string
Expand Down
62 changes: 0 additions & 62 deletions playground/mock/user.go

This file was deleted.

48 changes: 0 additions & 48 deletions playground/mock/user2.go

This file was deleted.

4 changes: 2 additions & 2 deletions realmain/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ func (r Runner) Check() {
if m.CheckSum != checksum {
// mock is not up to date
if source == "" {
log.Printf("[WARN] mock is not up to date. destination: %s", destination)
log.Printf("[ERROR] mock is not up to date. destination: %s", destination)
} else {
log.Printf("[WARN] mock is not up to date. source: %s, destination: %s", source, destination)
log.Printf("[ERROR] mock is not up to date. source: %s, destination: %s", source, destination)
}
isFail = true
}
Expand Down
7 changes: 6 additions & 1 deletion realmain/generate_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package realmain
import (
"log"
"os"
"path/filepath"

"github.com/sanposhiho/gomockhandler/model"
"github.com/sanposhiho/gomockhandler/realmain/util"
Expand All @@ -11,8 +12,12 @@ import (

// GenerateConfig generate config
func (r Runner) GenerateConfig() {
absRoot, err := filepath.Abs(r.Args.ProjectRoot)
if err != nil {
log.Fatalf("failed to get absolute project root: %w", err)
}
// create config in project root
configPath := r.Args.ProjectRoot + "/" + chunkrepo.Filename
configPath := absRoot + "/" + chunkrepo.Filename
chunk, err := r.ChunkRepo.Get(configPath)
if err != nil {
if !os.IsNotExist(err) {
Expand Down
2 changes: 1 addition & 1 deletion realmain/mockgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (r Runner) Mockgen() {
var destination string
switch m.Mode {
case model.Unknown:
log.Printf("unknown mock detected\n")
log.Printf("[WARN] unknown mock detected\n")
return nil
case model.ReflectMode:
err = m.ReflectModeRunner.Run()
Expand Down

0 comments on commit a359138

Please sign in to comment.