diff --git a/README.md b/README.md index b077383..ce0d706 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ The project started as a fork of testify, but over time it got its own runner an + [XSkip](#xskip) + [:rocket: Parametrized tests](#parametrized-test) + [Setup test](#setup-test) + + [Add ALLURE_ID to the tests before executing BeforeAll function](#Add-ALLURE_ID-to-the-tests-before-executing-BeforeAll-function) ## :zap: Features @@ -728,10 +729,10 @@ type ParametrizedSuite struct { ParamCities []string } -func (s *ParametrizedSuite) BeforeAll(t provider.T) { +func (s *ParametrizedSuite) InitTestParams() { for i := 0; i < 10; i++ { s.ParamCities = append(s.ParamCities, fake.City()) - } + } } func (s *ParametrizedSuite) TableTestCities(t provider.T, city string) { @@ -805,3 +806,39 @@ func TestRunner(t *testing.T) { Allure output: ![](.resources/example_setup_test.png) + +### [Add ALLURE_ID to the tests before executing BeforeAll function](examples/suite_demo/allureid_test.go) + +Function `AddAllureIDMapping(testName, allureID string)` allows to set ALLURE_ID label to the test during the suit's tests collecting step. +If the code into `BeforeAll` function fails, Allure Report will not duplicate testcases in TestOps. + +Test code: + +```go +package suite_demo + +import ( + "testing" + + "github.com/ozontech/allure-go/pkg/framework/provider" + "github.com/ozontech/allure-go/pkg/framework/suite" +) + +type AllureIdSuite struct { + suite.Suite +} + +func (s *AllureIdSuite) BeforeAll(t provider.T) { + // code that can fail here +} + +func (s *AllureIdSuite) TestMyTestWithAllureID(t provider.T) { + // code of your test here +} + +func TestNewDemo(t *testing.T) { + ais := new(AllureIdSuite) + ais.AddAllureIDMapping("TestMyTestWithAllureID", "12345") + suite.RunSuite(t, ais) +} +``` \ No newline at end of file diff --git a/examples/suite_demo/allureid_test.go b/examples/suite_demo/allureid_test.go new file mode 100644 index 0000000..2df0442 --- /dev/null +++ b/examples/suite_demo/allureid_test.go @@ -0,0 +1,26 @@ +package suite_demo + +import ( + "testing" + + "github.com/ozontech/allure-go/pkg/framework/provider" + "github.com/ozontech/allure-go/pkg/framework/suite" +) + +type AllureIdSuite struct { + suite.Suite +} + +func (s *AllureIdSuite) BeforeAll(t provider.T) { + // code that can fail here +} + +func (s *AllureIdSuite) TestMyTestWithAllureID(t provider.T) { + // code of your test here +} + +func TestNewDemo(t *testing.T) { + ais := new(AllureIdSuite) + ais.AddAllureIDMapping("TestMyTestWithAllureID", "12345") + suite.RunSuite(t, ais) +} diff --git a/pkg/framework/runner/interfaces.go b/pkg/framework/runner/interfaces.go index 67fa66f..3754e16 100644 --- a/pkg/framework/runner/interfaces.go +++ b/pkg/framework/runner/interfaces.go @@ -32,9 +32,17 @@ type AllureAfterSuite interface { AfterAll(t provider.T) } +// WithTestPramsSuite has an InitTestParams method, which will run before +// collecting the tests in the suite. +type WithTestPramsSuite interface { + InitTestParams() +} + type TestSuite interface { GetRunner() TestRunner SetRunner(runner TestRunner) + AddAllureIDMapping(testName, allureID string) + FindAllureID(testName string) (id string, ok bool) } type TestingT interface { diff --git a/pkg/framework/runner/suite_runner.go b/pkg/framework/runner/suite_runner.go index 114e379..a6b678f 100644 --- a/pkg/framework/runner/suite_runner.go +++ b/pkg/framework/runner/suite_runner.go @@ -62,11 +62,46 @@ func newSuiteRunner(realT TestingT, packageName, suiteName, parentSuite string, suite: suite, } r = collectTests(r, suite) + r = collectParametrizedTests(r, suite) r = collectHooks(r, suite) return r } +// collectParametrizedTests executes InitTestParams function, finds test methods with tableTestPrefix, +// gets map with parameters, gets map with parameterized tests, +// replaces tests in runner with parameterized tests with results +func collectParametrizedTests(runner *suiteRunner, suite TestSuite) *suiteRunner { + if initTestParamsSuit, ok := suite.(WithTestPramsSuite); ok { + initTestParamsSuit.InitTestParams() + } + newTests := make(map[string]Test) + for k, v := range runner.tests { + newTests[k] = v + } + for name, test := range runner.tests { + if strings.HasPrefix(name, tableTestPrefix) { + params, err := getParams(runner.suite, name) + if err != nil { + panic(err) + } + temp := getParamTests(test, params) + delete(newTests, name) + for tName, body := range temp { + tResult := body.GetMeta().GetResult() + id, ok := suite.FindAllureID(tName) + if ok { + tResult.AddLabel(allure.IDAllureLabel(id)) + } + newTests[tName] = body + runner.internalT.GetProvider().GetSuiteMeta().GetContainer().AddChild(tResult.UUID) + } + } + } + runner.tests = newTests + return runner +} + // collectTests filters suite methods according to set regular expression and // adds filtered methods to tests of runner func collectTests(runner *suiteRunner, suite TestSuite) *suiteRunner { @@ -81,7 +116,7 @@ func collectTests(runner *suiteRunner, suite TestSuite) *suiteRunner { method := methodFinder.Method(i) ok, err := methodFilter(method.Name) if err != nil { - _, _ = fmt.Fprintf(os.Stderr, "allire-go: invalid regexp for -m: %s\n", err) + _, _ = fmt.Fprintf(os.Stderr, "allure-go: invalid regexp for -m: %s\n", err) os.Exit(1) } @@ -90,6 +125,10 @@ func collectTests(runner *suiteRunner, suite TestSuite) *suiteRunner { } testMeta := adapter.NewTestMeta(suiteFullName, suiteName, method.Name, packageName) + id, ok := suite.FindAllureID(method.Name) + if ok { + testMeta.GetResult().AddLabel(allure.IDAllureLabel(id)) + } runner.tests[method.Name] = &testMethod{ testMeta: testMeta, testBody: method, @@ -107,34 +146,6 @@ type parametrizedTest interface { GetMeta() provider.TestMeta } -// parametrizedWrap executes beforeAll function, finds test methods with tableTestPrefix, -// gets map with parameters, gets map with parameterized tests, -// replaces tests in runner with parameterized tests with results -func parametrizedWrap(runner *suiteRunner, beforeAll func(provider.T)) func(t provider.T) { - return func(t provider.T) { - beforeAll(t) - newTests := make(map[string]Test) - for k, v := range runner.tests { - newTests[k] = v - } - for name, test := range runner.tests { - if strings.HasPrefix(name, tableTestPrefix) { - params, err := getParams(runner.suite, name) - if err != nil { - panic(err) - } - temp := getParamTests(test, params) - delete(newTests, name) - for tName, body := range temp { - newTests[tName] = body - runner.internalT.GetProvider().GetSuiteMeta().GetContainer().AddChild(body.GetMeta().GetResult().UUID) - } - } - } - runner.tests = newTests - } -} - // getParamTests create instance of TestAdapter for every param from params // and returns map whose elements are a pair (, ) func getParamTests(parentTest Test, params map[string]interface{}) map[string]Test { @@ -204,7 +215,7 @@ func getParams(suite TestSuite, methodName string) (res map[string]interface{}, func collectHooks(runner *suiteRunner, suite TestSuite) *suiteRunner { if beforeAll, ok := suite.(AllureBeforeSuite); ok { - runner.BeforeAll(parametrizedWrap(runner, beforeAll.BeforeAll)) + runner.BeforeAll(beforeAll.BeforeAll) } if beforeEach, ok := suite.(AllureBeforeTest); ok { diff --git a/pkg/framework/suite/suite.go b/pkg/framework/suite/suite.go index 28e97ec..1a94b01 100644 --- a/pkg/framework/suite/suite.go +++ b/pkg/framework/suite/suite.go @@ -10,7 +10,20 @@ import ( ) type Suite struct { - runner runner.TestRunner + runner runner.TestRunner + allureIDMapping map[string]string +} + +func (s *Suite) AddAllureIDMapping(testName, allureID string) { + if s.allureIDMapping == nil { + s.allureIDMapping = make(map[string]string) + } + s.allureIDMapping[testName] = allureID +} + +func (s *Suite) FindAllureID(testName string) (id string, ok bool) { + id, ok = s.allureIDMapping[testName] + return } func (s *Suite) GetRunner() runner.TestRunner {