+ Сценарий: Добавление сгенерированных функций в 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)
|
||||||
|
}
|
Загрузка…
Создание таблицы
Сослаться в новой задаче