+ Сценарий: Добавление сгенерированных функций в test-файл
Этот коммит содержится в:
родитель
4e3e82b79e
коммит
6f2a5fef98
6 изменённых файлов: 293 добавлений и 0 удалений
99
pkg/formatters/ast/ast.go
Обычный файл
99
pkg/formatters/ast/ast.go
Обычный файл
|
@ -0,0 +1,99 @@
|
|||
package ast
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
|
||||
"errors"
|
||||
)
|
||||
|
||||
type ASTer struct {
|
||||
pkg string
|
||||
fname string
|
||||
fset *token.FileSet
|
||||
node *ast.File
|
||||
}
|
||||
|
||||
func NewASTer() (*ASTer, error) {
|
||||
a := &ASTer{}
|
||||
|
||||
pkg, err := получитьИмяGoПакетаВЭтойДире()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a.pkg = pkg
|
||||
|
||||
err = a.найтиТестовыйФайл()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (a *ASTer) ДобавитьТестовуюФункцию(func_name string) error {
|
||||
return a.добавитьвФайлФункцию(func_name)
|
||||
}
|
||||
|
||||
func (a *ASTer) найтиТестовыйФайл() error {
|
||||
a.сгенеритьИмяФайла()
|
||||
_, err := os.Stat(a.fname)
|
||||
return err
|
||||
}
|
||||
func (a *ASTer) сгенеритьИмяФайла() {
|
||||
a.fname = a.pkg + "_test.go"
|
||||
}
|
||||
|
||||
func (a *ASTer) добавитьвФайлФункцию(func_name string) error {
|
||||
err := a.спарситьФайлиДобавитьФункцию(func_name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.перезаписатьФайл()
|
||||
}
|
||||
func (a *ASTer) спарситьФайлиДобавитьФункцию(func_name string) error {
|
||||
err := a.спарситьФайл()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fun := a.пустаяФункция(func_name)
|
||||
a.node.Decls = append(a.node.Decls, fun)
|
||||
return nil
|
||||
}
|
||||
func (a *ASTer) спарситьФайл() error {
|
||||
fset := token.NewFileSet()
|
||||
node, err := parser.ParseFile(fset, a.fname, nil, parser.ParseComments)
|
||||
a.fset = fset
|
||||
a.node = node
|
||||
return err
|
||||
}
|
||||
func (a *ASTer) пустаяФункция(func_name string) *ast.FuncDecl {
|
||||
return &ast.FuncDecl{
|
||||
Name: ast.NewIdent(func_name),
|
||||
Type: &ast.FuncType{
|
||||
Params: &ast.FieldList{},
|
||||
Results: &ast.FieldList{},
|
||||
},
|
||||
Body: &ast.BlockStmt{},
|
||||
}
|
||||
}
|
||||
|
||||
func (a *ASTer) перезаписатьФайл() error {
|
||||
err := переименоватьФайлСоВременем(a.fname)
|
||||
if err != nil {
|
||||
return errors.Join(err, errors.New("cant backup orig file"))
|
||||
}
|
||||
|
||||
f, err := os.Create(a.fname)
|
||||
if err != nil {
|
||||
return errors.Join(err, errors.New("cant rewrite orig file"))
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return format.Node(f, a.fset, a.node)
|
||||
}
|
68
pkg/formatters/ast/ast_test.go
Обычный файл
68
pkg/formatters/ast/ast_test.go
Обычный файл
|
@ -0,0 +1,68 @@
|
|||
package ast
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"git.golang1.ru/softonik/godog"
|
||||
"git.golang1.ru/softonik/godog/pkg/lib"
|
||||
. "git.golang1.ru/softonik/godog_and_gomega"
|
||||
. "github.com/onsi/gomega"
|
||||
. "github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type testData struct {
|
||||
tempdir string
|
||||
}
|
||||
|
||||
var (
|
||||
t *testData
|
||||
)
|
||||
|
||||
func resetTestData() {
|
||||
t = &testData{}
|
||||
}
|
||||
func beforeSuite() {
|
||||
CharactersAroundMismatchToInclude = 20
|
||||
}
|
||||
func afterSuite() {
|
||||
}
|
||||
|
||||
func beforeScenario() {
|
||||
resetTestData()
|
||||
createTempDir()
|
||||
}
|
||||
func afterScenario() {
|
||||
rmTempDir()
|
||||
}
|
||||
|
||||
func createTempDir() {
|
||||
dir := filepath.Clean(os.TempDir())
|
||||
tempDir, err := os.MkdirTemp(dir, "test-")
|
||||
Ok(err)
|
||||
t.tempdir = tempDir
|
||||
err = os.Chdir(t.tempdir)
|
||||
Ok(err)
|
||||
}
|
||||
|
||||
func rmTempDir() {
|
||||
err := os.RemoveAll(t.tempdir)
|
||||
Ok(err)
|
||||
}
|
||||
|
||||
// -----------------------
|
||||
|
||||
func файл(fname string, content *godog.DocString) {
|
||||
err := lib.WriteFile(fname, content.Content)
|
||||
Ok(err)
|
||||
}
|
||||
func добавленаТестоваяФункция(func_name string) {
|
||||
err := ДобавитьТестовуюФункцию(func_name)
|
||||
Ok(err)
|
||||
}
|
||||
func файлДолженСодержать(fname string, content *godog.DocString) {
|
||||
cont, err := lib.ReadFile(fname)
|
||||
Ok(err)
|
||||
|
||||
Ω(cont).To(Be(content.Content))
|
||||
}
|
18
pkg/formatters/ast/features/app.feature
Обычный файл
18
pkg/formatters/ast/features/app.feature
Обычный файл
|
@ -0,0 +1,18 @@
|
|||
# language: ru
|
||||
Функционал: AST-редактир go-файлов
|
||||
Сгенерированные функции автоматически добавляются в тест-файл текущего пакета
|
||||
|
||||
Сценарий: Добавление сгенерированных функций в тест-файл
|
||||
Дано Файл "mypkg_test.go":
|
||||
```
|
||||
package mypkg
|
||||
```
|
||||
Когда Добавлена тестовая функция "ПриветМир"
|
||||
То Файл "mypkg_test.go" должен содержать:
|
||||
```
|
||||
package mypkg
|
||||
|
||||
func ПриветМир() {
|
||||
}
|
||||
|
||||
```
|
10
pkg/formatters/ast/global.go
Обычный файл
10
pkg/formatters/ast/global.go
Обычный файл
|
@ -0,0 +1,10 @@
|
|||
package ast
|
||||
|
||||
func ДобавитьТестовуюФункцию(f string) error {
|
||||
a, err := NewASTer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.ДобавитьТестовуюФункцию(f)
|
||||
}
|
50
pkg/formatters/ast/helpers.go
Обычный файл
50
pkg/formatters/ast/helpers.go
Обычный файл
|
@ -0,0 +1,50 @@
|
|||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"errors"
|
||||
)
|
||||
|
||||
func получитьИмяGoПакетаВЭтойДире() (pkg_name string, err_ret error) {
|
||||
err_ret = errors.New("not found")
|
||||
|
||||
filepath.WalkDir(".", func(path string, info os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() && filepath.Ext(path) == ".go" {
|
||||
pkg, err := получитьИмяGoПакетаФайла(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pkg_name = pkg
|
||||
err_ret = nil
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
func получитьИмяGoПакетаФайла(fname string) (string, error) {
|
||||
fset := token.NewFileSet()
|
||||
node, err := parser.ParseFile(fset, fname, nil, parser.PackageClauseOnly)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return node.Name.Name, nil
|
||||
}
|
||||
|
||||
func переименоватьФайлСоВременем(fname string) error {
|
||||
currentTime := time.Now()
|
||||
timestamp := currentTime.Format("20060102_150405")
|
||||
new_fname := fmt.Sprintf("%v_%v", fname, timestamp)
|
||||
return os.Rename(fname, new_fname)
|
||||
}
|
48
pkg/formatters/ast/init_test.go
Обычный файл
48
pkg/formatters/ast/init_test.go
Обычный файл
|
@ -0,0 +1,48 @@
|
|||
package ast
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.golang1.ru/softonik/godog"
|
||||
"git.golang1.ru/softonik/godog/colors"
|
||||
. "git.golang1.ru/softonik/godog_and_gomega"
|
||||
)
|
||||
|
||||
func InitializeScenario(ctx *godog.ScenarioContext) {
|
||||
ctx.Step(`^Файл "([^"]*)":$`, файл)
|
||||
ctx.Step(`^Добавлена тестовая функция "([^"]*)"$`, добавленаТестоваяФункция)
|
||||
ctx.Step(`^Файл "([^"]*)" должен содержать:$`, файлДолженСодержать)
|
||||
|
||||
// -----------------------
|
||||
ctx.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
|
||||
beforeScenario()
|
||||
return ctx, nil
|
||||
})
|
||||
ctx.After(func(ctx context.Context, sc *godog.Scenario, err error) (context.Context, error) {
|
||||
afterScenario()
|
||||
return ctx, nil
|
||||
})
|
||||
InitializeGomegaForGodog(ctx)
|
||||
}
|
||||
|
||||
func InitializeSuite(tsc *godog.TestSuiteContext) {
|
||||
tsc.BeforeSuite(beforeSuite)
|
||||
tsc.AfterSuite(afterSuite)
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var opts = godog.Options{
|
||||
Output: colors.Colored(os.Stdout),
|
||||
Strict: true,
|
||||
StopOnFailure: true,
|
||||
}
|
||||
r := godog.TestSuite{
|
||||
Name: "app",
|
||||
TestSuiteInitializer: InitializeSuite,
|
||||
ScenarioInitializer: InitializeScenario,
|
||||
Options: &opts,
|
||||
}.Run()
|
||||
os.Exit(r)
|
||||
}
|
Загрузка…
Создание таблицы
Сослаться в новой задаче