From 0c27c021338ddb5efde1f3e6feef85ed97637aa5 Mon Sep 17 00:00:00 2001 From: Wenbo han Date: Sun, 30 Jul 2023 21:35:43 +0800 Subject: [PATCH] Add testing feature --- README.md | 1 + README_zh.md | 1 + foundation/application.go | 66 +++++++++++-- foundation/console/stubs.go | 38 ++++++++ foundation/console/test_make_command.go | 99 ++++++++++++++++++++ foundation/console/test_make_command_test.go | 32 +++++++ log/logger/daily.go | 2 + log/logger/single.go | 3 + support/constant.go | 7 +- testing/test_case.go | 4 + 10 files changed, 242 insertions(+), 11 deletions(-) create mode 100644 foundation/console/stubs.go create mode 100644 foundation/console/test_make_command.go create mode 100644 foundation/console/test_make_command_test.go create mode 100644 testing/test_case.go diff --git a/README.md b/README.md index e6ca62908..4a7fb3d2d 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ This project exists thanks to all the people who contribute, to participate in t + ## Group diff --git a/README_zh.md b/README_zh.md index d1e3ea87b..dae6bcb4c 100644 --- a/README_zh.md +++ b/README_zh.md @@ -66,6 +66,7 @@ Laravel! + ## 群组 diff --git a/foundation/application.go b/foundation/application.go index c162d31d5..f2ae8c556 100644 --- a/foundation/application.go +++ b/foundation/application.go @@ -18,6 +18,8 @@ var ( App foundation.Application ) +var flagEnv = flag.String("env", ".env", "custom .env path") + func init() { setEnv() @@ -46,6 +48,7 @@ func (app *Application) Boot() { app.registerConfiguredServiceProviders() app.bootConfiguredServiceProviders() app.registerCommands([]consolecontract.Command{ + console.NewTestMakeCommand(), console.NewPackageMakeCommand(), console.NewVendorPublishCommand(app.publishes, app.publishGroups), }) @@ -183,16 +186,32 @@ func setEnv() { } } - var env *string - if !flag.Parsed() && support.Env != support.EnvTest { - env = flag.String("env", ".env", "custom .env path") - flag.Parse() - } else { - testEnv := ".env" - env = &testEnv + env := getEnvPath() + if support.Env == support.EnvTest { + var ( + relativePath string + envExist bool + testEnv = env + ) + + for i := 0; i < 50; i++ { + if _, err := os.Stat(testEnv); err == nil { + envExist = true + + break + } else { + testEnv = filepath.Join("../", testEnv) + relativePath = filepath.Join("../", relativePath) + } + } + + if envExist { + env = testEnv + support.RelativePath = relativePath + } } - support.EnvPath = *env + support.EnvPath = env } func setRootPath() { @@ -206,3 +225,34 @@ func setRootPath() { support.RootPath = rootPath } + +func getEnvPath() string { + envPath := ".env" + args := os.Args + for index, arg := range args { + if strings.HasPrefix(arg, "--env=") { + path := strings.TrimPrefix(arg, "--env=") + + if path != "" { + envPath = path + break + } + } + if strings.HasPrefix(arg, "-env=") { + path := strings.TrimPrefix(arg, "-env=") + + if path != "" { + envPath = path + break + } + } + if arg == "--env" || arg == "-env" { + if len(args) >= index+1 && !strings.HasPrefix(args[index+1], "-") { + envPath = args[index+1] + break + } + } + } + + return envPath +} diff --git a/foundation/console/stubs.go b/foundation/console/stubs.go new file mode 100644 index 000000000..3bcaffd10 --- /dev/null +++ b/foundation/console/stubs.go @@ -0,0 +1,38 @@ +package console + +type Stubs struct { +} + +func (r Stubs) Test() string { + return `package DummyPackage + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "goravel/tests" +) + +type DummyTestSuite struct { + suite.Suite + tests.TestCase +} + +func TestDummyTestSuite(t *testing.T) { + suite.Run(t, new(DummyTestSuite)) +} + +// SetupTest will run before each test in the suite. +func (s *UserTestSuite) SetupTest() { +} + +// TearDownTest will run after each test in the suite. +func (s *UserTestSuite) TearDownTest() { +} + +func (s *UserTestSuite) TestIndex() { + // TODO +} +` +} diff --git a/foundation/console/test_make_command.go b/foundation/console/test_make_command.go new file mode 100644 index 000000000..72c3746fd --- /dev/null +++ b/foundation/console/test_make_command.go @@ -0,0 +1,99 @@ +package console + +import ( + "errors" + "os" + "path/filepath" + "strings" + + "github.com/gookit/color" + + "github.com/goravel/framework/contracts/console" + "github.com/goravel/framework/contracts/console/command" + "github.com/goravel/framework/support/file" + "github.com/goravel/framework/support/str" +) + +type TestMakeCommand struct { +} + +func NewTestMakeCommand() *TestMakeCommand { + return &TestMakeCommand{} +} + +// Signature The name and signature of the console command. +func (receiver *TestMakeCommand) Signature() string { + return "make:test" +} + +// Description The console command description. +func (receiver *TestMakeCommand) Description() string { + return "Create a new test class" +} + +// Extend The console command extend. +func (receiver *TestMakeCommand) Extend() command.Extend { + return command.Extend{ + Category: "make", + } +} + +// Handle Execute the console command. +func (receiver *TestMakeCommand) Handle(ctx console.Context) error { + name := ctx.Argument(0) + if name == "" { + return errors.New("Not enough arguments (missing: name) ") + } + + stub := receiver.getStub() + + if err := file.Create(receiver.getPath(name), receiver.populateStub(stub, name)); err != nil { + return err + } + + color.Greenln("Test created successfully") + + return nil +} + +func (receiver *TestMakeCommand) getStub() string { + return Stubs{}.Test() +} + +// populateStub Populate the place-holders in the command stub. +func (receiver *TestMakeCommand) populateStub(stub string, name string) string { + controllerName, packageName, _ := receiver.parseName(name) + + stub = strings.ReplaceAll(stub, "DummyTest", str.Case2Camel(controllerName)) + stub = strings.ReplaceAll(stub, "DummyPackage", packageName) + + return stub +} + +// getPath Get the full path to the command. +func (receiver *TestMakeCommand) getPath(name string) string { + pwd, _ := os.Getwd() + + controllerName, _, folderPath := receiver.parseName(name) + + return filepath.Join(pwd, "tests", folderPath, str.Camel2Case(controllerName)+".go") +} + +// parseName Parse the name to get the controller name, package name and folder path. +func (receiver *TestMakeCommand) parseName(name string) (string, string, string) { + name = strings.TrimSuffix(name, ".go") + + segments := strings.Split(name, "/") + + controllerName := segments[len(segments)-1] + + packageName := "tests" + folderPath := "" + + if len(segments) > 1 { + folderPath = filepath.Join(segments[:len(segments)-1]...) + packageName = segments[len(segments)-2] + } + + return controllerName, packageName, folderPath +} diff --git a/foundation/console/test_make_command_test.go b/foundation/console/test_make_command_test.go new file mode 100644 index 000000000..1ede35b7c --- /dev/null +++ b/foundation/console/test_make_command_test.go @@ -0,0 +1,32 @@ +package console + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + consolemocks "github.com/goravel/framework/contracts/console/mocks" + "github.com/goravel/framework/support/file" +) + +func TestTestMakeCommand(t *testing.T) { + testMakeCommand := &TestMakeCommand{} + mockContext := &consolemocks.Context{} + mockContext.On("Argument", 0).Return("").Once() + err := testMakeCommand.Handle(mockContext) + assert.EqualError(t, err, "Not enough arguments (missing: name) ") + + mockContext.On("Argument", 0).Return("UserTest").Once() + err = testMakeCommand.Handle(mockContext) + assert.Nil(t, err) + assert.True(t, file.Exists("tests/user_test.go")) + + mockContext.On("Argument", 0).Return("user/UserTest").Once() + err = testMakeCommand.Handle(mockContext) + assert.Nil(t, err) + assert.True(t, file.Exists("tests/user/user_test.go")) + assert.True(t, file.Contain("tests/user/user_test.go", "package user")) + assert.True(t, file.Contain("tests/user/user_test.go", "type UserTestSuite struct")) + assert.True(t, file.Contain("tests/user/user_test.go", "func (s *UserTestSuite) SetupTest() {")) + assert.Nil(t, file.Remove("tests")) +} diff --git a/log/logger/daily.go b/log/logger/daily.go index ae750a38a..f7d77bfe9 100644 --- a/log/logger/daily.go +++ b/log/logger/daily.go @@ -12,6 +12,7 @@ import ( "github.com/goravel/framework/contracts/config" "github.com/goravel/framework/log/formatter" + "github.com/goravel/framework/support" ) type Daily struct { @@ -33,6 +34,7 @@ func (daily *Daily) Handle(channel string) (logrus.Hook, error) { ext := filepath.Ext(logPath) logPath = strings.ReplaceAll(logPath, ext, "") + logPath = filepath.Join(support.RelativePath, logPath) writer, err := rotatelogs.New( logPath+"-%Y-%m-%d"+ext, diff --git a/log/logger/single.go b/log/logger/single.go index 8f86faffb..347c62695 100644 --- a/log/logger/single.go +++ b/log/logger/single.go @@ -2,12 +2,14 @@ package logger import ( "errors" + "path/filepath" "github.com/rifflock/lfshook" "github.com/sirupsen/logrus" "github.com/goravel/framework/contracts/config" "github.com/goravel/framework/log/formatter" + "github.com/goravel/framework/support" ) type Single struct { @@ -26,6 +28,7 @@ func (single *Single) Handle(channel string) (logrus.Hook, error) { return nil, errors.New("error log path") } + logPath = filepath.Join(support.RelativePath, logPath) levels := getLevels(single.config.GetString(channel + ".level")) pathMap := lfshook.PathMap{} for _, level := range levels { diff --git a/support/constant.go b/support/constant.go index 5aed24277..5f6035ea8 100644 --- a/support/constant.go +++ b/support/constant.go @@ -9,7 +9,8 @@ const ( ) var ( - Env = EnvRuntime - EnvPath = ".env" - RootPath string + Env = EnvRuntime + EnvPath string + RelativePath string + RootPath string ) diff --git a/testing/test_case.go b/testing/test_case.go new file mode 100644 index 000000000..374f5a8ed --- /dev/null +++ b/testing/test_case.go @@ -0,0 +1,4 @@ +package testing + +type TestCase struct { +}