├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ └── main.yml
├── .gitignore
├── .golangci.yaml
├── .pre-commit-config.yaml
├── .resources
├── allure_go_icon.svg
├── allure_icon.svg
├── example_async_test.png
├── example_attachments.png
├── example_befores_afters.png
├── example_multiple_suites_run.png
├── example_sample_provider.png
├── example_setup_test.png
├── example_step_tree.png
├── example_table_test.png
├── example_xskip.png
├── scheme_runnerRunSuite.png
└── scheme_runnerRunTest.png
├── LICENSE.md
├── Makefile
├── README.md
├── examples
├── allure_go_compare
│ ├── attachments_test.go
│ ├── before_after_test.go
│ └── test_test.go
├── async
│ ├── async_step_test.go
│ ├── async_suite_test.go
│ └── mixed_test.go
├── provider_demo
│ ├── sample_panic_test.go
│ └── sample_test.go
└── suite_demo
│ ├── attachments_test.go
│ ├── befores_afters_test.go
│ ├── fails_test.go
│ ├── labels_test.go
│ ├── links_test.go
│ ├── new_parametrized_test.go
│ ├── parameters_test.go
│ ├── parametrized_test.go
│ ├── running_test.go
│ ├── setup_test.go
│ ├── skip_test.go
│ ├── step_test.go
│ └── step_tree_test.go
├── go.mod
├── go.sum
└── pkg
├── allure
├── .golangci.yaml
├── Makefile
├── README.md
├── attachment.go
├── attachment_test.go
├── config.go
├── config_test.go
├── container.go
├── container_test.go
├── errors.go
├── file_manager.go
├── file_manager_test.go
├── go.mod
├── go.sum
├── label.go
├── label_test.go
├── link.go
├── link_test.go
├── parameter.go
├── parameter_test.go
├── result.go
├── result_test.go
├── status.go
├── status_detail.go
├── status_test.go
├── step.go
├── step_test.go
├── time.go
└── time_test.go
└── framework
├── .golangci.yaml
├── Makefile
├── README.md
├── asserts_wrapper
├── asserts
│ ├── asserts.go
│ └── asserts_test.go
├── helper
│ ├── asserts_helper.go
│ ├── asserts_helper_test.go
│ ├── helper.go
│ ├── helper_test.go
│ ├── interfaces.go
│ ├── require_helper.go
│ └── require_helper_test.go
├── require
│ ├── require.go
│ └── requires_test.go
└── wrapper
│ ├── helper.go
│ ├── helper_test.go
│ ├── interfaces.go
│ ├── wrapper.go
│ └── wrapper_test.go
├── core
├── allure_manager
│ ├── adapter
│ │ ├── suite_adapter.go
│ │ ├── suite_adapter_test.go
│ │ ├── test_adapter.go
│ │ └── test_adapter_test.go
│ ├── ctx
│ │ ├── hooks.go
│ │ ├── hooks_test.go
│ │ ├── test_ctx.go
│ │ └── test_ctx_test.go
│ ├── manager
│ │ ├── attachment.go
│ │ ├── attachment_test.go
│ │ ├── description.go
│ │ ├── description_test.go
│ │ ├── execution_management.go
│ │ ├── execution_management_test.go
│ │ ├── labels.go
│ │ ├── labels_test.go
│ │ ├── links.go
│ │ ├── links_test.go
│ │ ├── parameter.go
│ │ ├── parameter_test.go
│ │ ├── provider.go
│ │ ├── provider_config.go
│ │ ├── provider_config_test.go
│ │ ├── provider_test.go
│ │ ├── steps.go
│ │ └── steps_test.go
│ └── testplan
│ │ └── testplan.go
├── assert
│ ├── assertions.go
│ └── assertions_test.go
├── common
│ ├── common.go
│ ├── common_test.go
│ ├── errors_handling.go
│ ├── errors_handling_test.go
│ ├── hooks.go
│ ├── hooks_test.go
│ ├── interfaces.go
│ ├── step_context.go
│ ├── step_context_test.go
│ ├── steps.go
│ ├── steps_test.go
│ └── tempdir.go
└── constants
│ ├── constants.go
│ └── constants_test.go
├── go.mod
├── go.sum
├── provider
├── allure.go
├── provider.go
└── test.go
├── runner
├── contants.go
├── interfaces.go
├── runner.go
├── runner_test.go
├── suite_runner.go
└── tests.go
└── suite
├── suite.go
├── suite_runner_test.go
└── suite_test.go
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Used func: '...'
16 | 2. What you actually wanted to do: '...'
17 | 3. What has been expected: '...'
18 | 4. What you got actual: '....'
19 | 5. Error Log (if any): '...'
20 | 6. Allure-Report screenshot (if any): '...'
21 |
22 | **Expected behavior**
23 | A clear and concise description of what you expected to happen.
24 |
25 | **Screenshots**
26 | If applicable, add screenshots to help explain your problem.
27 |
28 | **Additional context**
29 | Add any other context about the problem here.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: [master]
6 | pull_request:
7 | branches: [master]
8 |
9 | workflow_dispatch:
10 |
11 | jobs:
12 | golangci:
13 | name: lint
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v4
17 | - uses: actions/setup-go@v5
18 | with:
19 | go-version: "1.17.8"
20 | - name: allure-golangci-lint
21 | run: cd ./pkg/allure && make lint
22 | - name: provider-golangci-lint
23 | run: cd ./pkg/framework && make lint
24 |
25 | test:
26 | runs-on: ubuntu-latest
27 | steps:
28 | - uses: actions/checkout@v4
29 | - name: allure-test
30 | run: cd ./pkg/allure && make test
31 | - name: provider-test
32 | run: cd ./pkg/framework && make test
33 |
34 | examples:
35 | name: examples
36 | runs-on: ubuntu-latest
37 | steps:
38 | - uses: actions/checkout@v4
39 | - name: Run examples
40 | run: make examples
41 | - name: Archive code coverage results
42 | uses: actions/upload-artifact@v4
43 | with:
44 | name: allure-results
45 | path: ./examples/allure-results
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | testdata/
3 | allure-results/
4 | bin/
5 |
6 | # MacOS
7 | .DS_Store
8 |
9 | # Binaries for programs and plugins
10 | *.exe
11 | *.exe~
12 | *.dll
13 | *.so
14 | *.dylib
15 |
16 | # Test binary, build with `go test -c`
17 | *.test
18 |
19 | # Output of the go coverage tool, specifically when used with LiteIDE
20 | *.out
21 |
--------------------------------------------------------------------------------
/.golangci.yaml:
--------------------------------------------------------------------------------
1 | # More info on config here: https://github.com/golangci/golangci-lint#config-file
2 | run:
3 | deadline: 10s
4 | timeout: 5m
5 | issues-exit-code: 1
6 | tests: true
7 | skip-dirs:
8 | - bin
9 | - vendor
10 | - var
11 | - tmp
12 | skip-files:
13 | - \.pb\.go$
14 | - \.pb\.goclay\.go$
15 | - \_test.go$
16 |
17 | output:
18 | format: colored-line-number
19 | print-issued-lines: true
20 | print-linter-name: true
21 |
22 | linters-settings:
23 | govet:
24 | check-shadowing: true
25 | golint:
26 | min-confidence: 0
27 | dupl:
28 | threshold: 100
29 | goconst:
30 | min-len: 2
31 | min-occurrences: 2
32 |
33 | linters:
34 | disable-all: true
35 | enable:
36 | - golint
37 | - govet
38 | - errcheck
39 | - deadcode
40 | - structcheck
41 | - varcheck
42 | - ineffassign
43 | - typecheck
44 | - dupl
45 | - goconst
46 | - gosec
47 | - goimports
48 | - megacheck
49 |
50 |
51 | issues:
52 | exclude-use-default: false
53 | exclude:
54 | # _ instead of err checks
55 | - G104
56 | - G306
57 | # md5 using for hash generation, not for security, so ignore this
58 | - G401
59 | - G501
60 | # for "public interface + private struct implementation" cases only!
61 | - exported func * returns unexported type *, which can be annoying to use
62 | # can be removed in the development phase
63 | # - (comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)
64 | # not for the active development - can be removed in the stable phase
65 | - should have a package comment, unless it's in another file for this package
66 | - don't use an underscore in package name
67 | # errcheck: Almost all programs ignore errors on these functions and in most cases it's ok
68 | - Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv|.*Rollback). is not checked
69 | - should check returned error before deferring
70 | - should have comment or be unexported
71 | - a blank import should be only in a main or test package
72 | - Can't process result by diff processor
73 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | - repo: https://github.com/dnephin/pre-commit-golang
2 | sha: HEAD
3 | hooks:
4 | - id: go-fmt
5 |
6 | - repo: https://github.com/pre-commit/pre-commit-hooks
7 | rev: v1.4.0
8 | hooks:
9 | - id: check-yaml
10 |
11 | - repo: https://github.com/Lucas-C/pre-commit-hooks-go
12 | sha: v1.0.0
13 | hooks:
14 | - id: checkmake
15 |
16 | - repo: local
17 | hooks:
18 | - id: golangci-lint
19 | language: system
20 | name: Golangci linter
21 | entry: make lint
22 |
23 | #- repo: local
24 | # hooks:
25 | # - id: unit-tests
26 | # language: system
27 | # name: Unit tests
28 | # entry: make test
--------------------------------------------------------------------------------
/.resources/allure_go_icon.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/.resources/allure_icon.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/.resources/example_async_test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ozontech/allure-go/94107284580cfff6e668a259a9470a3021aa5ea1/.resources/example_async_test.png
--------------------------------------------------------------------------------
/.resources/example_attachments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ozontech/allure-go/94107284580cfff6e668a259a9470a3021aa5ea1/.resources/example_attachments.png
--------------------------------------------------------------------------------
/.resources/example_befores_afters.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ozontech/allure-go/94107284580cfff6e668a259a9470a3021aa5ea1/.resources/example_befores_afters.png
--------------------------------------------------------------------------------
/.resources/example_multiple_suites_run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ozontech/allure-go/94107284580cfff6e668a259a9470a3021aa5ea1/.resources/example_multiple_suites_run.png
--------------------------------------------------------------------------------
/.resources/example_sample_provider.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ozontech/allure-go/94107284580cfff6e668a259a9470a3021aa5ea1/.resources/example_sample_provider.png
--------------------------------------------------------------------------------
/.resources/example_setup_test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ozontech/allure-go/94107284580cfff6e668a259a9470a3021aa5ea1/.resources/example_setup_test.png
--------------------------------------------------------------------------------
/.resources/example_step_tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ozontech/allure-go/94107284580cfff6e668a259a9470a3021aa5ea1/.resources/example_step_tree.png
--------------------------------------------------------------------------------
/.resources/example_table_test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ozontech/allure-go/94107284580cfff6e668a259a9470a3021aa5ea1/.resources/example_table_test.png
--------------------------------------------------------------------------------
/.resources/example_xskip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ozontech/allure-go/94107284580cfff6e668a259a9470a3021aa5ea1/.resources/example_xskip.png
--------------------------------------------------------------------------------
/.resources/scheme_runnerRunSuite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ozontech/allure-go/94107284580cfff6e668a259a9470a3021aa5ea1/.resources/scheme_runnerRunSuite.png
--------------------------------------------------------------------------------
/.resources/scheme_runnerRunTest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ozontech/allure-go/94107284580cfff6e668a259a9470a3021aa5ea1/.resources/scheme_runnerRunTest.png
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | APP?=allure-go
2 | RELEASE?=0.6.0
3 | GOOS?=darwin
4 |
5 | COMMIT?=$(shell git rev-parse --short HEAD)
6 | BUILD_TIME?=$(shell date -u '+%Y-%m-%d_%H:%M:%S')
7 |
8 | export GO111MODULE=on
9 | export GOSUMDB=off
10 | LOCAL_BIN:=$(CURDIR)/bin
11 | EXAMPLES_TAGS:=examples_new,provider_new,allure_go_new,async
12 |
13 | ##################### GOLANG-CI RELATED CHECKS #####################
14 | # Check global GOLANGCI-LINT
15 | GOLANGCI_BIN:=$(LOCAL_BIN)/golangci-lint
16 | GOLANGCI_TAG:=1.38.0
17 |
18 | # Check local bin version
19 | ifneq ($(wildcard $(GOLANGCI_BIN)),)
20 | GOLANGCI_BIN_VERSION:=$(shell $(GOLANGCI_BIN) --version)
21 | ifneq ($(GOLANGCI_BIN_VERSION),)
22 | GOLANGCI_BIN_VERSION_SHORT:=$(shell echo "$(GOLANGCI_BIN_VERSION)" | sed -E 's/.* version (.*) built from .* on .*/\1/g')
23 | else
24 | GOLANGCI_BIN_VERSION_SHORT:=0
25 | endif
26 | ifneq "$(GOLANGCI_TAG)" "$(word 1, $(sort $(GOLANGCI_TAG) $(GOLANGCI_BIN_VERSION_SHORT)))"
27 | GOLANGCI_BIN:=
28 | endif
29 | endif
30 |
31 | # Check global bin version
32 | ifneq (, $(shell which golangci-lint))
33 | GOLANGCI_VERSION:=$(shell golangci-lint --version 2> /dev/null )
34 | ifneq ($(GOLANGCI_VERSION),)
35 | GOLANGCI_VERSION_SHORT:=$(shell echo "$(GOLANGCI_VERSION)"|sed -E 's/.* version (.*) built from .* on .*/\1/g')
36 | else
37 | GOLANGCI_VERSION_SHORT:=0
38 | endif
39 | ifeq "$(GOLANGCI_TAG)" "$(word 1, $(sort $(GOLANGCI_TAG) $(GOLANGCI_VERSION_SHORT)))"
40 | GOLANGCI_BIN:=$(shell which golangci-lint)
41 | endif
42 | endif
43 | ##################### GOLANG-CI RELATED CHECKS #####################
44 |
45 | .PHONY: full-demo
46 | full-demo: install demo
47 |
48 | .PHONY: demo
49 | demo: examples allure-serve
50 |
51 | .PHONY: install
52 | install: .install_deps .install_allure
53 |
54 | .PHONY: .install_deps
55 | .install_deps:
56 | go mod tidy && go mod download
57 |
58 | .PHONY: .install_allure
59 | .install_allure:
60 | ifeq ($(OS),Windows_NT)
61 | $(info Run Windows run pattern...)
62 | $(info Make sure scoop installed at your system. Check for more information: https://github.com/ScoopInstaller/Scoop#installation)
63 | scoop install allure
64 | endif
65 | ifeq ($(OS),Linux)
66 | $(info Run Linux run pattern...)
67 | $(info Make sure you have sudo rights for the system.)
68 | sudo apt-add-repository ppa:qameta/allure
69 | sudo apt-get update
70 | sudo apt-get install allure
71 | endif
72 | ifeq ($(OS),Darwin)
73 | $(info Run installation for Darwin OS)
74 | $(info Make sure brew installed at your system. Check for more information: https://docs.brew.sh/Installation)
75 | brew install allure
76 | endif
77 |
78 | .PHONY: examples
79 | examples:
80 | ifeq ($(OS),Windows_NT)
81 | $(info Run windows pattern...)
82 | set ALLURE_OUTPUT_PATH=../&& go test ./examples/... --tags=$(EXAMPLES_TAGS)
83 | else
84 | $(info Run default pattern...)
85 | export ALLURE_OUTPUT_PATH=../ && go test ./examples/... --tags=$(EXAMPLES_TAGS) || true
86 | endif
87 |
88 | .PHONY: allure-serve
89 | allure-serve:
90 | allure serve ./examples/allure-results
91 |
92 | # run full lint like in pipeline
93 | .PHONY: lint
94 | lint: install-lint
95 | $(GOLANGCI_BIN) run --config=.golangci.yaml ./... --build-tags=$(EXAMPLES_TAGS)
96 |
97 | .PHONY: install-lint
98 | install-lint:
99 | ifeq ($(wildcard $(GOLANGCI_BIN)),)
100 | $(info #Downloading golangci-lint v$(GOLANGCI_TAG))
101 | tmp=$$(mktemp -d) && cd $$tmp && pwd && go mod init temp && go get -d github.com/golangci/golangci-lint/cmd/golangci-lint@v$(GOLANGCI_TAG) && \
102 | go build -ldflags "-X 'main.version=$(GOLANGCI_TAG)' -X 'main.commit=test' -X 'main.date=test'" -o $(LOCAL_BIN)/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint && \
103 | rm -rf $$tmp
104 | GOLANGCI_BIN:=$(LOCAL_BIN)/golangci-lint
105 | endif
106 |
--------------------------------------------------------------------------------
/examples/allure_go_compare/attachments_test.go:
--------------------------------------------------------------------------------
1 | //go:build allure_go_new
2 | // +build allure_go_new
3 |
4 | package allure_go_compare
5 |
6 | import (
7 | "testing"
8 |
9 | "github.com/ozontech/allure-go/pkg/allure"
10 | "github.com/ozontech/allure-go/pkg/framework/provider"
11 | "github.com/ozontech/allure-go/pkg/framework/suite"
12 | )
13 |
14 | type AllureGoAttachments struct {
15 | suite.Suite
16 | }
17 |
18 | /* Allure-Go style:
19 | func TestTextAttachment(t *testing.T) {
20 | allure.Test(t, allure.Description("Testing a text attachment"), allure .Action(func() {
21 | _ = allure.AddAttachments("text!", allure.TextPlain, []byte("Some text!"))
22 | }))
23 | }
24 | */
25 |
26 | func (s *AllureGoAttachments) TestTextAttachment(t provider.T) {
27 | t.Epic("Compare with allure-go")
28 | t.Description("Testing a text attachment")
29 | t.WithAttachments(allure.NewAttachment("text!", allure.Text, []byte("Some text!")))
30 | }
31 |
32 | /* TestTextAttachmentToStep Allure-Go style:
33 | func TestTextAttachmentToStep(t *testing.T) {
34 | allure.Test(t, allure.Description("Testing a text attachment"), allure.Action(func() {
35 | allure.Step(allure.Description("adding a text attachment"), allure.Action(func() {
36 | _ = allure.AddAttachments("text!", allure.TextPlain, []byte("Some text!"))
37 | }))
38 | }))
39 | }
40 | */
41 |
42 | func (s *AllureGoAttachments) TestTextAttachmentToStepV1(t provider.T) {
43 | t.Epic("Compare with allure-go")
44 | t.Description("Testing a text attachment")
45 | t.WithNewStep("adding a text attachment", func(ctx provider.StepCtx) {
46 | ctx.WithAttachments(allure.NewAttachment("text!", allure.Text, []byte("Some text!")))
47 | })
48 | }
49 |
50 | func (s *AllureGoAttachments) TestTextAttachmentToStepV2(t provider.T) {
51 | t.Epic("Compare with allure-go")
52 | t.Description("Testing a text attachment")
53 | t.Step(allure.NewSimpleStep("adding a text attachment").
54 | WithAttachments(allure.NewAttachment("text!", allure.Text, []byte("Some text!"))))
55 | }
56 |
57 | func (s *AllureGoAttachments) TestTextAttachmentToStepV3(t provider.T) {
58 | t.Epic("Compare with allure-go")
59 | t.Description("Testing a text attachment")
60 | step := allure.NewSimpleStep("adding a text attachment")
61 | step.WithAttachments(allure.NewAttachment("text!", allure.Text, []byte("Some text!")))
62 | t.Step(step)
63 | }
64 |
65 | // Also we provide some complex actions with steps
66 | // In this example we initialize step, declare it like nested and add new attachment to it.
67 |
68 | func (s *AllureGoAttachments) TestTextAttachmentToStepV4(t provider.T) {
69 | t.Epic("Compare with allure-go")
70 | t.Description("Testing a text attachment")
71 | step := allure.NewSimpleStep("adding a text attachment")
72 | step.WithAttachments(allure.NewAttachment("text!", allure.Text, []byte("Some text!")))
73 | t.WithNewStep("step", func(ctx provider.StepCtx) {
74 | ctx.WithAttachments(allure.NewAttachment("text inside step!", allure.Text, []byte("Another text!")))
75 | })
76 | }
77 |
78 | func TestAllureGoAttachments(t *testing.T) {
79 | suite.RunSuite(t, new(AllureGoAttachments))
80 | }
81 |
--------------------------------------------------------------------------------
/examples/allure_go_compare/before_after_test.go:
--------------------------------------------------------------------------------
1 | //go:build allure_go_new
2 | // +build allure_go_new
3 |
4 | package allure_go_compare
5 |
6 | import (
7 | "testing"
8 |
9 | "github.com/ozontech/allure-go/pkg/framework/provider"
10 | "github.com/ozontech/allure-go/pkg/framework/suite"
11 | )
12 |
13 | type AllureGoBeforesAfters struct {
14 | suite.Suite
15 | }
16 |
17 | /* Allure-Go style:
18 | func TestAllureSetupTeardown(t *testing.T) {
19 | allure.BeforeTest(t,
20 | allure.Description("setup"),
21 | allure.Action(func() {
22 | allure.Step(
23 | allure.Description("Setup step 1"),
24 | allure.Action(func() {}))
25 | }))
26 |
27 | allure.Test(t,
28 | allure.Description("actual test"),
29 | allure.Action(func() {
30 | allure.Step(
31 | allure.Description("Test step 1"),
32 | allure.Action(func() {}))
33 | }))
34 |
35 | allure.AfterTest(t,
36 | allure.Description("teardown"),
37 | allure.Action(func() {
38 | allure.Step(
39 | allure.Description("teardown step 1"),
40 | allure.Action(func() {}))
41 | }))
42 | }
43 | */
44 |
45 | // We provide even more! but without infinite breakers ({(((({(({()}))}))))})
46 | //func (s AllureGoBeforesAfters) BeforeAll() {
47 | // s.NewStep("Setup suite step 1")
48 | //}
49 | //
50 | //func (s AllureGoBeforesAfters) AfterAll() {
51 | // s.NewStep("Teardown suite step 1")
52 | //}
53 |
54 | func (s AllureGoBeforesAfters) BeforeEach(t provider.T) {
55 | t.NewStep("Setup test step 1")
56 | }
57 |
58 | func (s AllureGoBeforesAfters) AfterEach(t provider.T) {
59 | t.NewStep("Teardown test step 1")
60 | }
61 |
62 | func (s AllureGoBeforesAfters) TestBeforesAfters(t provider.T) {
63 | t.Epic("Compare with allure-go")
64 | t.NewStep("Test step 1")
65 | }
66 |
67 | func TestAllureGoBeforesAfters(t *testing.T) {
68 | suite.RunSuite(t, new(AllureGoBeforesAfters))
69 | }
70 |
--------------------------------------------------------------------------------
/examples/allure_go_compare/test_test.go:
--------------------------------------------------------------------------------
1 | //go:build allure_go_new
2 | // +build allure_go_new
3 |
4 | package allure_go_compare
5 |
6 | import (
7 | "testing"
8 |
9 | "github.com/ozontech/allure-go/pkg/framework/provider"
10 | "github.com/ozontech/allure-go/pkg/framework/suite"
11 | )
12 |
13 | type SuiteStruct struct {
14 | suite.Suite
15 | }
16 |
17 | func (s *SuiteStruct) TestNewTest(t provider.T) {
18 | t.Epic("Compare with allure-go")
19 | t.Description("New Test Description")
20 | t.WithNewStep("Step description", func(ctx provider.StepCtx) {
21 |
22 | })
23 | }
24 |
25 | /* Allure-Go style:
26 | func TestWithIntricateSubsteps(t *testing.T) {
27 | allure.Test(t, allure.Description("Test"),
28 | allure.Action(func() {
29 | allure.Step(allure.Description("Step 1"), allure.Action(func() {
30 | doSomething()
31 | allure.Step(allure.Description("Sub-step 1.1"), allure.Action(func() {
32 | t.Errorf("Failure")
33 | }))
34 | allure.Step(allure.Description("Sub-step 1.2"), allure.Action(func() {}))
35 | allure.SkipStep(allure.Description("Sub-step 1.3"), allure.Reason("Skip this step because of defect to be fixed"), allure.Action(func() {}))
36 | }))
37 | allure.Step(allure.Description("Step 2"), allure.Action(func() {
38 | allure.Step(allure.Description("Sub-step 2.1"), allure.Action(func() {
39 | allure.Step(allure.Description("Step 2.1.1"), allure.Action(func() {
40 | allure.Step(allure.Description("Sub-step 2.1.1.1"), allure.Action(func() {
41 | t.Errorf("Failure")
42 | }))
43 | allure.Step(allure.Description("Sub-step 2.1.1.2"), allure.Action(func() {
44 | t.Error("Failed like this")
45 | }))
46 | }))
47 | }))
48 | allure.Step(allure.Description("Sub-step 2.2"), allure.Action(func() {}))
49 | }))
50 | }))
51 | }
52 | */
53 |
54 | func doSomething(ctx provider.StepCtx) {
55 | ctx.WithNewStep("Something", func(ctx provider.StepCtx) {
56 | ctx.WithNewStep("Because We Can!", func(ctx provider.StepCtx) {
57 |
58 | })
59 | })
60 | }
61 |
62 | // Works even better! each step will have his real status, but parent will be failed anyway
63 |
64 | func (s *SuiteStruct) TestWithIntricateSubsteps(t provider.T) {
65 | t.Epic("Compare with allure-go")
66 | t.Description("Test")
67 |
68 | t.WithNewStep("Step 1", func(ctx provider.StepCtx) {
69 | doSomething(ctx)
70 | ctx.WithNewStep("Sub-step 1.1", func(ctx provider.StepCtx) {
71 | ctx.Error("Failure Sub-step 1.1")
72 | })
73 | ctx.WithNewStep("Sub-step 1.2", func(ctx provider.StepCtx) {
74 |
75 | })
76 | ctx.WithNewStep("Sub-step 1.3", func(ctx provider.StepCtx) {
77 |
78 | })
79 | })
80 | t.WithNewStep("Step 2", func(ctx provider.StepCtx) {
81 | ctx.WithNewStep("Sub-Step 2.1", func(ctx provider.StepCtx) {
82 | ctx.WithNewStep("Sub-step 2.1.1", func(ctx provider.StepCtx) {
83 | ctx.WithNewStep("Sub-step 2.1.1.1", func(ctx provider.StepCtx) {
84 | ctx.Error("Failure Sub-step 2.1.1.1")
85 | })
86 | ctx.WithNewStep("Sub-step 2.1.1.2", func(ctx provider.StepCtx) {
87 | ctx.Error("This will be in report-status. Sub-step 2.1.1.2")
88 | })
89 | })
90 | })
91 | ctx.WithNewStep("Sub-Step 2.2", func(ctx provider.StepCtx) {
92 |
93 | })
94 | })
95 | }
96 |
97 | func TestRun(t *testing.T) {
98 | suite.RunSuite(t, new(SuiteStruct))
99 | }
100 |
--------------------------------------------------------------------------------
/examples/async/async_suite_test.go:
--------------------------------------------------------------------------------
1 | //go:build async
2 | // +build async
3 |
4 | package async
5 |
6 | import (
7 | "fmt"
8 | "testing"
9 | "time"
10 |
11 | "github.com/ozontech/allure-go/pkg/framework/provider"
12 | "github.com/ozontech/allure-go/pkg/framework/suite"
13 | )
14 |
15 | type SuiteAsyncDemo struct {
16 | suite.Suite
17 | }
18 |
19 | func (s *SuiteAsyncDemo) BeforeEach(t provider.T) {
20 | t.Epic("Async")
21 | t.Feature("Async Suite")
22 | t.Tags("async", "suite", "steps")
23 | }
24 |
25 | func (s *SuiteAsyncDemo) TestAsyncSuiteDemo1(t provider.T) {
26 | t.Title("Async Test 1")
27 |
28 | startSign := fmt.Sprintf("%s", time.Now())
29 | t.Parallel()
30 | t.WithNewStep("Sync Step Demo", func(ctx provider.StepCtx) {
31 | ctx.WithNewParameters("Start", startSign)
32 | ctx.Logf("Test 1 Started At: %s", startSign)
33 | time.Sleep(3 * time.Second)
34 | stopSign := fmt.Sprintf("%s", time.Now())
35 | ctx.Logf("Test 1 Stopped At: %s", stopSign)
36 | ctx.WithNewParameters("Stop", stopSign)
37 | })
38 | }
39 |
40 | func (s *SuiteAsyncDemo) TestAsyncSuiteDemo2(t provider.T) {
41 | t.Title("Async Test 2")
42 |
43 | startSign := fmt.Sprintf("%s", time.Now())
44 | t.Parallel()
45 | t.WithNewStep("Sync Step Demo", func(ctx provider.StepCtx) {
46 | ctx.WithNewParameters("Start", startSign)
47 | ctx.Logf("Test 2 Started At: %s", startSign)
48 | time.Sleep(3 * time.Second)
49 | stopSign := fmt.Sprintf("%s", time.Now())
50 | ctx.Logf("Test 2 Stopped At: %s", stopSign)
51 | ctx.WithNewParameters("Stop", stopSign)
52 | })
53 | }
54 |
55 | func (s *SuiteAsyncDemo) TestAsyncSuiteDemo3(t provider.T) {
56 | t.Title("Async Test 3")
57 | t.Description(`
58 | This test should be failed. But all logs a correct.`)
59 |
60 | startSign := fmt.Sprintf("%s", time.Now())
61 | t.Parallel()
62 | t.WithNewStep("Sync Step Demo", func(ctx provider.StepCtx) {
63 | ctx.WithNewParameters("Start", startSign)
64 | ctx.Logf("Test 3 Started At: %s", startSign)
65 | time.Sleep(1 * time.Second)
66 | defer func() {
67 | stopSign := fmt.Sprintf("%s", time.Now())
68 | ctx.Logf("Test 3 Stopped At: %s", stopSign)
69 | ctx.WithNewParameters("Stop", stopSign)
70 | }()
71 | ctx.Require().False(true)
72 | })
73 | }
74 |
75 | func (s *SuiteAsyncDemo) TestAsyncSuiteDemo4(t provider.T) {
76 | t.Title("Async Test 4")
77 | t.Description(`
78 | This test should be panic. But all logs a correct.`)
79 |
80 | startSign := fmt.Sprintf("%s", time.Now())
81 | t.Parallel()
82 | t.WithNewStep("Sync Step Demo", func(ctx provider.StepCtx) {
83 | ctx.WithNewParameters("Start", startSign)
84 | ctx.Logf("Test 4 Started At: %s", startSign)
85 | time.Sleep(2 * time.Second)
86 | defer func() {
87 | stopSign := fmt.Sprintf("%s", time.Now())
88 | ctx.Logf("Test 4 Stopped At: %s", stopSign)
89 | ctx.WithNewParameters("Stop", stopSign)
90 | }()
91 | panic("Whoops")
92 | })
93 | }
94 |
95 | func TestSuiteAsyncRunner(t *testing.T) {
96 | suite.RunSuite(t, new(SuiteAsyncDemo))
97 | }
98 |
--------------------------------------------------------------------------------
/examples/async/mixed_test.go:
--------------------------------------------------------------------------------
1 | package async
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/ozontech/allure-go/pkg/framework/provider"
7 | "github.com/ozontech/allure-go/pkg/framework/suite"
8 | )
9 |
10 | type MixedAsyncSuite struct {
11 | suite.Suite
12 | }
13 |
14 | func (s *MixedAsyncSuite) BeforeEach(t provider.T) {
15 | t.Epic("Async")
16 | t.Feature("Mixed Suite")
17 | t.Tags("async", "suite", "steps")
18 | }
19 |
20 | func (s *MixedAsyncSuite) TestSelectionProductsLists(t provider.T) {
21 | t.SkipOnPrint()
22 | testCases := []struct {
23 | testName string
24 | }{{"test1"}, {"test2"}, {"test3"}}
25 |
26 | for _, tc := range testCases {
27 | t.Run(tc.testName, func(t provider.T) {
28 | name := tc.testName
29 | t.Parallel()
30 | t.NewStep(name)
31 | })
32 | }
33 | }
34 |
35 | func (s *MixedAsyncSuite) TestSelectionProductsLists2(t provider.T) {
36 | t.SkipOnPrint()
37 | t.Parallel()
38 | testCases := []struct {
39 | testName string
40 | }{{"test1"}, {"test2"}, {"test3"}}
41 |
42 | for _, tc := range testCases {
43 | t.Run(tc.testName, func(t provider.T) {
44 | name := tc.testName
45 | t.Parallel()
46 | t.NewStep(name)
47 | })
48 | }
49 | }
50 |
51 | func (s *MixedAsyncSuite) TestSelectionProductsLists3(t provider.T) {
52 | t.SkipOnPrint()
53 | testCases := []struct {
54 | testName string
55 | }{{"test1"}, {"test2"}, {"test3"}}
56 |
57 | for _, tc := range testCases {
58 | t.Run(tc.testName, func(t provider.T) {
59 | name := tc.testName
60 | t.Parallel()
61 | t.NewStep(name)
62 | t.Fatalf("WHOOPS")
63 | })
64 | }
65 | }
66 |
67 | func (s *MixedAsyncSuite) TestSelectionProductsLists4(t provider.T) {
68 | t.SkipOnPrint()
69 | testCases := []struct {
70 | testName string
71 | }{{"test1"}, {"test2"}, {"test3"}}
72 |
73 | for _, tc := range testCases {
74 | t.Run(tc.testName, func(t provider.T) {
75 | name := tc.testName
76 | t.Parallel()
77 | t.NewStep(name)
78 | panic("WHOOPS")
79 | })
80 | }
81 | }
82 |
83 | func TestMixedAsyncSuite(t *testing.T) {
84 | suite.RunSuite(t, new(MixedAsyncSuite))
85 | }
86 |
--------------------------------------------------------------------------------
/examples/provider_demo/sample_panic_test.go:
--------------------------------------------------------------------------------
1 | //go:build provider_new
2 | // +build provider_new
3 |
4 | package provider_demo
5 |
6 | import (
7 | "testing"
8 |
9 | "github.com/ozontech/allure-go/pkg/framework/provider"
10 | "github.com/ozontech/allure-go/pkg/framework/runner"
11 | )
12 |
13 | func TestPanicProviderDemo(realT *testing.T) {
14 | r := runner.NewRunner(realT, realT.Name())
15 | r.BeforeEach(func(t provider.T) {
16 | t.Epic("Only Provider Demo")
17 | t.Feature("runner.RunTest")
18 | })
19 | r.NewTest("Test1", func(t provider.T) {
20 | t.Title("Some Panic test 1")
21 | t.Description("allure-go allows you to use allure without suites. Even if it panics or failed")
22 | panic("whoops")
23 | })
24 |
25 | r.NewTest("Test3", func(t provider.T) {
26 | t.Title("Some Failed test 2")
27 | t.Description("allure-go allows you to use allure without suites. Even if it panics or failed")
28 | t.Require().NotNil(nil)
29 | })
30 |
31 | r.NewTest("Test2", func(t provider.T) {
32 | t.Title("Some Normal test 2")
33 | t.Description("allure-go allows you to use allure without suites. Even if it panics or failed")
34 | })
35 |
36 | r.RunTests()
37 | }
38 |
--------------------------------------------------------------------------------
/examples/provider_demo/sample_test.go:
--------------------------------------------------------------------------------
1 | //go:build provider_new
2 | // +build provider_new
3 |
4 | package provider_demo
5 |
6 | import (
7 | "fmt"
8 | "testing"
9 |
10 | "github.com/ozontech/allure-go/pkg/allure"
11 | "github.com/ozontech/allure-go/pkg/framework/provider"
12 | "github.com/ozontech/allure-go/pkg/framework/runner"
13 | )
14 |
15 | func TestSampleDemo(t *testing.T) {
16 | runner.Run(t, "My test", func(t provider.T) {
17 | t.Epic("Only Provider Demo")
18 | t.Feature("runner.RunTest")
19 |
20 | t.Title("Some Sample test")
21 | t.Description("allure-go allows you to use allure without suites")
22 | t.WithParameters(allure.NewParameter("host", "localhost"))
23 |
24 | t.WithNewStep("Some nested step", func(ctx provider.StepCtx) {
25 | ctx.WithNewStep("Some inner step 1", func(ctx provider.StepCtx) {
26 | ctx.WithNewStep("Some inner step 1.1", func(ctx provider.StepCtx) {
27 |
28 | })
29 | })
30 | ctx.WithNewStep("Some inner step 2", func(ctx provider.StepCtx) {
31 | ctx.WithNewStep("Some inner step 2.1", func(ctx provider.StepCtx) {
32 |
33 | })
34 | })
35 | })
36 | }, "Sample", "Provider-only", "No provider initialization")
37 | }
38 |
39 | func TestOtherSampleDemo(realT *testing.T) {
40 | r := runner.NewRunner(realT, realT.Name())
41 |
42 | r.BeforeEach(func(t provider.T) {
43 | t.NewStep(fmt.Sprintf("This is before test step for %s", t.Name()))
44 | })
45 | r.BeforeAll(func(t provider.T) {
46 | t.NewStep(fmt.Sprintf("This is BeforeAll test step for %s", t.Name()))
47 | })
48 | r.AfterEach(func(t provider.T) {
49 | t.NewStep(fmt.Sprintf("This is AfterEach test step for %s", t.Name()))
50 | })
51 | r.AfterAll(func(t provider.T) {
52 | t.NewStep(fmt.Sprintf("This is AfterAll test step for %s", t.Name()))
53 | })
54 |
55 | r.NewTest("My test 1", func(t provider.T) {
56 | t.Epic("Only Provider Demo")
57 | t.Feature("T.Run()")
58 |
59 | t.Title("Some Other Sample test")
60 | t.Description("allure-testify allows you to use allure without suites")
61 |
62 | t.WithNewStep("Some nested step", func(ctx provider.StepCtx) {
63 | ctx.WithNewStep("Some inner step 1", func(ctx provider.StepCtx) {
64 | ctx.WithNewStep("Some inner step 1.1", func(ctx provider.StepCtx) {
65 |
66 | })
67 | })
68 | ctx.WithNewStep("Some inner step 2", func(ctx provider.StepCtx) {
69 | ctx.WithNewStep("Some inner step 2.1", func(ctx provider.StepCtx) {
70 |
71 | })
72 | })
73 | })
74 | }, "Sample", "Provider-only", "with provider initialization")
75 |
76 | r.RunTests()
77 | }
78 |
--------------------------------------------------------------------------------
/examples/suite_demo/befores_afters_test.go:
--------------------------------------------------------------------------------
1 | //go:build examples_new
2 | // +build examples_new
3 |
4 | package suite_demo
5 |
6 | import (
7 | "testing"
8 |
9 | "github.com/ozontech/allure-go/pkg/framework/provider"
10 | "github.com/ozontech/allure-go/pkg/framework/suite"
11 | )
12 |
13 | type BeforeAfterDemoSuite struct {
14 | suite.Suite
15 | }
16 |
17 | func (s *BeforeAfterDemoSuite) BeforeEach(t provider.T) {
18 | t.NewStep("Before Test Step")
19 | }
20 |
21 | func (s *BeforeAfterDemoSuite) AfterEach(t provider.T) {
22 | t.NewStep("After Test Step")
23 | }
24 |
25 | func (s *BeforeAfterDemoSuite) BeforeAll(t provider.T) {
26 | t.NewStep("Before suite Step")
27 | }
28 |
29 | func (s *BeforeAfterDemoSuite) AfterAll(t provider.T) {
30 | t.NewStep("After suite Step")
31 | t.Logf("HI")
32 | }
33 |
34 | func (s *BeforeAfterDemoSuite) TestBeforeAfterTest(t provider.T) {
35 | t.Epic("Demo")
36 | t.Feature("BeforeAfter")
37 | t.Title("Test wrapped with SetUp & TearDown")
38 | t.Description(`
39 | This test wrapped with SetUp and TearDown container.`)
40 |
41 | t.Tags("BeforeAfter")
42 | }
43 |
44 | func TestBeforesAfters(t *testing.T) {
45 | t.Parallel()
46 | suite.RunSuite(t, new(BeforeAfterDemoSuite))
47 | }
48 |
--------------------------------------------------------------------------------
/examples/suite_demo/labels_test.go:
--------------------------------------------------------------------------------
1 | //go:build examples_new
2 | // +build examples_new
3 |
4 | package suite_demo
5 |
6 | import (
7 | "testing"
8 |
9 | "github.com/ozontech/allure-go/pkg/allure"
10 | "github.com/ozontech/allure-go/pkg/framework/provider"
11 | "github.com/ozontech/allure-go/pkg/framework/suite"
12 | )
13 |
14 | type LabelsDemoSuite struct {
15 | suite.Suite
16 | }
17 |
18 | func (s *LabelsDemoSuite) BeforeEach(t provider.T) {
19 | t.Epic("Demo")
20 | t.Feature("Labels")
21 | t.Story("Story Label")
22 |
23 | t.Owner("John Doe")
24 | t.Lead("John Doe's Boss")
25 |
26 | t.Tag("EachTestTag")
27 | }
28 |
29 | func (s *LabelsDemoSuite) TestLabelsExample1(t provider.T) {
30 | t.Title("Labels Demo Example 1")
31 | t.Description(`
32 | This Test will have all labels from SetupTest function
33 | Unique labels:
34 | ID = "example1"
35 | Severity = "blocker"
36 | Unique tag = "Example1"
37 | Also this test has additional "suite" label`)
38 |
39 | t.ID("Id example1")
40 | t.Severity(allure.BLOCKER)
41 |
42 | t.AddSuiteLabel("AnotherSuite")
43 |
44 | t.Tag("Example1")
45 | }
46 |
47 | func (s *LabelsDemoSuite) TestLabelsExample2(t provider.T) {
48 | t.Title("Labels Demo Example 2")
49 | t.Description(`
50 | This Test will have all labels from SetupTest function
51 | Unique labels:
52 | ID = "example2"
53 | Severity = "critical"
54 | Unique tag = "Example2"
55 | Also this test has additional "parentSuite" label`)
56 |
57 | t.ID("example2")
58 | t.Severity(allure.CRITICAL)
59 |
60 | t.AddParentSuite("AnotherParentSuite")
61 |
62 | t.Tag("Example2")
63 | }
64 |
65 | func (s *LabelsDemoSuite) TestLabelsExample3(t provider.T) {
66 | t.Title("Labels Demo Example 3")
67 | t.Description(`
68 | This Test will have all labels from SetupTest function
69 | Unique labels:
70 | ID = "example3"
71 | Severity = "normal"
72 | Unique tag = "Example3"
73 | Also this test has additional "subSuite" label`)
74 |
75 | t.ID("example3")
76 | t.Severity(allure.NORMAL)
77 |
78 | t.AddSubSuite("SomeSubSuite")
79 |
80 | t.Tag("Example3")
81 | }
82 |
83 | func (s *LabelsDemoSuite) TestLabelsExample4(t provider.T) {
84 | t.Title("Labels Demo Example 4")
85 | t.Description(`
86 | This Test will have all labels from SetupTest function
87 | Unique labels:
88 | ID = "example4"
89 | Severity = "minor"
90 | Unique tag = "Example4"`)
91 |
92 | t.ID("example4")
93 | t.Severity(allure.MINOR)
94 |
95 | t.Tag("Example4")
96 | }
97 |
98 | func (s *LabelsDemoSuite) TestLabelsExample5(t provider.T) {
99 | t.Title("Labels Demo Example 5")
100 | t.Description(`
101 | This Test will have all labels from SetupTest function
102 | Unique labels:
103 | ID = "example5"
104 | Severity = "trivial"
105 | Unique tag = "Example5"`)
106 |
107 | t.ID("example5")
108 | t.Severity(allure.TRIVIAL)
109 |
110 | t.Tag("Example5")
111 | }
112 |
113 | func TestLabels(t *testing.T) {
114 | t.Parallel()
115 | suite.RunSuite(t, new(LabelsDemoSuite))
116 | }
117 |
--------------------------------------------------------------------------------
/examples/suite_demo/links_test.go:
--------------------------------------------------------------------------------
1 | //go:build examples_new
2 | // +build examples_new
3 |
4 | package suite_demo
5 |
6 | import (
7 | "os"
8 | "testing"
9 |
10 | "github.com/ozontech/allure-go/pkg/allure"
11 | "github.com/ozontech/allure-go/pkg/framework/provider"
12 | "github.com/ozontech/allure-go/pkg/framework/suite"
13 | )
14 |
15 | type LinkDemoSuite struct {
16 | suite.Suite
17 | }
18 |
19 | func (s *LinkDemoSuite) BeforeAll(t provider.T) {
20 | _ = os.Setenv("ALLURE_TESTCASE_PATTERN", "https://tour.golang.org/welcome/%s")
21 | _ = os.Setenv("ALLURE_ISSUE_PATTERN", "https://pkg.go.dev/%s")
22 | }
23 |
24 | func (s *LinkDemoSuite) AfterAll(t provider.T) {
25 | _ = os.Setenv("ALLURE_TESTCASE_PATTERN", "")
26 | _ = os.Setenv("ALLURE_ISSUE_PATTERN", "")
27 | }
28 |
29 | func (s *LinkDemoSuite) TestLinks(t provider.T) {
30 | t.Epic("Demo")
31 | t.Feature("Links")
32 | t.Title("Test contains links")
33 | t.Description(`
34 | This test contains link with ISSUE, TEST CASE and LINK.
35 | Test case link: https://tour.golang.org/welcome/1
36 | Issue link: https://pkg.go.dev/github.com/stretchr/testify
37 | Link link: https://www.makeuseof.com/tag/8-purrfect-cat-websites/`)
38 |
39 | t.Tags("Links")
40 |
41 | t.SetTestCase("1")
42 | t.SetIssue("github.com/stretchr/testify")
43 |
44 | link := "https://www.makeuseof.com/tag/8-purrfect-cat-websites/"
45 | t.Link(allure.LinkLink("Demo Link", link))
46 | }
47 |
48 | func TestLinks(t *testing.T) {
49 | t.Parallel()
50 | suite.RunSuite(t, new(LinkDemoSuite))
51 | }
52 |
--------------------------------------------------------------------------------
/examples/suite_demo/new_parametrized_test.go:
--------------------------------------------------------------------------------
1 | //go:build examples_new
2 | // +build examples_new
3 |
4 | package suite_demo
5 |
6 | import (
7 | "testing"
8 |
9 | "github.com/jackc/fake"
10 | "github.com/ozontech/allure-go/pkg/framework/provider"
11 | "github.com/ozontech/allure-go/pkg/framework/suite"
12 | )
13 |
14 | type ParametrizedSuite struct {
15 | suite.Suite
16 | ParamCities []string
17 | }
18 |
19 | func (s *ParametrizedSuite) BeforeAll(t provider.T) {
20 | for i := 0; i < 10; i++ {
21 | s.ParamCities = append(s.ParamCities, fake.City())
22 | }
23 | }
24 |
25 | func (s *ParametrizedSuite) TableTestCities(t provider.T, city string) {
26 | t.Parallel()
27 | t.Require().NotEmpty(city)
28 | }
29 |
30 | func TestNewParametrizedDemo(t *testing.T) {
31 | suite.RunSuite(t, new(ParametrizedSuite))
32 | }
33 |
--------------------------------------------------------------------------------
/examples/suite_demo/parameters_test.go:
--------------------------------------------------------------------------------
1 | //go:build examples_new
2 | // +build examples_new
3 |
4 | package suite_demo
5 |
6 | import (
7 | "testing"
8 |
9 | "github.com/ozontech/allure-go/pkg/allure"
10 | "github.com/ozontech/allure-go/pkg/framework/provider"
11 | "github.com/ozontech/allure-go/pkg/framework/suite"
12 | )
13 |
14 | type ParametersDemoSuite struct {
15 | suite.Suite
16 | }
17 |
18 | func (s *ParametersDemoSuite) TestAddParameterToStep(t provider.T) {
19 | t.Epic("Demo")
20 | t.Feature("Parameters")
21 | t.Title("Add Parameters to step")
22 | t.Description(`
23 | Step A will contain following parameters:
24 | Param1 = Val1
25 | Param2 = Val2
26 | Param3 = Val3
27 | Param4 = Val4
28 | Param5 = Val5
29 | Param6 = Val6
30 | Param7 = Val7`)
31 |
32 | t.Tags("Steps", "Nesting", "Parameters")
33 |
34 | step := allure.NewSimpleStep("Step A")
35 |
36 | // with step.WithParameters(s) function
37 | step.WithParameters(allure.NewParameter("Param1", "Val1"))
38 | step.WithParameters(allure.NewParameters("Param2", "Val2", "Param3", "Val3", "Param4", "Val4")...)
39 |
40 | // don't forget register your step :)
41 | t.Step(step)
42 | }
43 |
44 | func (s *ParametersDemoSuite) TestAddParameterToNestedStep(t provider.T) {
45 | t.Epic("Demo")
46 | t.Feature("Parameters")
47 | t.Title("Add parameters to Nested Steps")
48 | t.Description(`
49 | Step A is parent step for Step B
50 | Step A contains Param 1 and Param 4
51 | Step B contains Param 2 and Param 3`)
52 |
53 | t.Tags("Steps", "Nesting", "Parameters")
54 |
55 | t.WithNewStep("Step A", func(ctx provider.StepCtx) {
56 | ctx.WithNewParameters("Param 1", "Value 1")
57 | ctx.WithNewStep("Step B", func(ctx provider.StepCtx) {
58 | ctx.WithNewParameters("Param 2", "Value 2", "Param 3", "Value 3")
59 | })
60 | ctx.WithNewParameters("Param 4", "Value 3")
61 | })
62 | }
63 |
64 | func TestParameters(t *testing.T) {
65 | t.Parallel()
66 | suite.RunSuite(t, new(ParametersDemoSuite))
67 | }
68 |
--------------------------------------------------------------------------------
/examples/suite_demo/parametrized_test.go:
--------------------------------------------------------------------------------
1 | //go:build examples_new
2 | // +build examples_new
3 |
4 | package suite_demo
5 |
6 | import (
7 | "fmt"
8 | "testing"
9 |
10 | "github.com/ozontech/allure-go/pkg/framework/provider"
11 | "github.com/ozontech/allure-go/pkg/framework/suite"
12 | )
13 |
14 | type ParametrizedTestDemo struct {
15 | suite.Suite
16 | }
17 |
18 | func (s *ParametrizedTestDemo) BeforeEach(t provider.T) {
19 | t.Epic("Demo")
20 | t.Feature("Parametrized")
21 | }
22 |
23 | func (s *ParametrizedTestDemo) TestParameterized(t provider.T) {
24 | t.Title("Parent Test")
25 | t.Description(`
26 | This test is parent for all Parametrized`)
27 |
28 | for i := 0; i < 10; i++ {
29 | newI := i
30 | t.Run(fmt.Sprintf("Parametrized #%d", newI), func(t provider.T) {
31 | t.Feature("Parametrized")
32 | t.Description(fmt.Sprintf("This test checks that 1 Equal %d", newI))
33 | t.Tag("Parametrized")
34 | t.Parallel()
35 | t.WithNewStep(fmt.Sprintf("Step %d", i), func(ctx provider.StepCtx) {
36 | ctx.Require().Equal(1, newI)
37 | })
38 | })
39 | }
40 |
41 | for i := 0; i < 10; i++ {
42 | newI := i
43 | t.Run(fmt.Sprintf("Parametrized 2#%d", newI), func(t provider.T) {
44 | t.Feature("Parametrized")
45 | t.Description(fmt.Sprintf("This test checks that 1 Equal %d", newI))
46 | t.Tag("Parametrized")
47 | t.Parallel()
48 | t.WithNewStep(fmt.Sprintf("Step %d", newI), func(ctx provider.StepCtx) {
49 | ctx.Require().Less(1, newI)
50 | })
51 | })
52 | }
53 | }
54 |
55 | func TestParametrizedDemo(t *testing.T) {
56 | suite.RunSuite(t, new(ParametrizedTestDemo))
57 | }
58 |
59 | type ParametrizedTestDemo2 struct {
60 | suite.Suite
61 | }
62 |
63 | func (s *ParametrizedTestDemo2) BeforeEach(t provider.T) {
64 | t.Epic("Demo")
65 | t.Feature("Parametrized")
66 | }
67 |
68 | func (s *ParametrizedTestDemo2) TestParameterized2(t provider.T) {
69 | t.Title("Parent Test")
70 | t.Description(`
71 | This test is parent for all Parametrized`)
72 |
73 | for i := 0; i < 10; i++ {
74 | newI := i
75 | t.Run(fmt.Sprintf("Parametrized #%d", newI), func(t provider.T) {
76 | t.Feature("Parametrized")
77 | t.Description(fmt.Sprintf("This test checks that 1 Equal %d", newI))
78 | t.Tag("Parametrized")
79 | t.WithNewStep(fmt.Sprintf("Step %d", newI), func(ctx provider.StepCtx) {
80 | ctx.Require().Equal(1, newI)
81 | })
82 | })
83 | }
84 |
85 | for i := 0; i < 10; i++ {
86 | newI := i
87 | t.Run(fmt.Sprintf("Parametrized 2#%d", newI), func(t provider.T) {
88 | t.Feature("Parametrized")
89 | t.Description(fmt.Sprintf("This test checks that 1 Equal %d", newI))
90 | t.Tag("Parametrized")
91 | t.WithNewStep(fmt.Sprintf("Step %d", newI), func(ctx provider.StepCtx) {
92 | if newI == 4 {
93 | panic("WHOOPS")
94 | }
95 | ctx.Require().Less(1, newI)
96 | })
97 | })
98 | }
99 | }
100 |
101 | func TestParametrizedDemo2(t *testing.T) {
102 | suite.RunSuite(t, new(ParametrizedTestDemo2))
103 | }
104 |
--------------------------------------------------------------------------------
/examples/suite_demo/running_test.go:
--------------------------------------------------------------------------------
1 | //go:build examples_new
2 | // +build examples_new
3 |
4 | package suite_demo
5 |
6 | import (
7 | "github.com/ozontech/allure-go/pkg/framework/provider"
8 | "testing"
9 |
10 | "github.com/ozontech/allure-go/pkg/framework/suite"
11 | )
12 |
13 | // TestRunningDemoSuite demonstrate parallel running
14 | type TestRunningDemoSuite struct {
15 | suite.Suite
16 | }
17 |
18 | func (s *TestRunningDemoSuite) TestBeforesAfters(t provider.T) {
19 | t.Parallel()
20 | s.RunSuite(t, new(BeforeAfterDemoSuite))
21 | }
22 |
23 | func (s *TestRunningDemoSuite) TestFails(t provider.T) {
24 | t.Parallel()
25 | s.RunSuite(t, new(FailsDemoSuite))
26 | }
27 |
28 | func (s *TestRunningDemoSuite) TestLabels(t provider.T) {
29 | t.Parallel()
30 | s.RunSuite(t, new(LabelsDemoSuite))
31 | }
32 |
33 | func (s *TestRunningDemoSuite) TestParametrized(t provider.T) {
34 | t.Parallel()
35 | s.RunSuite(t, new(ParametrizedSuite))
36 | }
37 |
38 | func TestRunDemo(t *testing.T) {
39 | // use RunSuite to run suite of suites
40 | t.Parallel()
41 | suite.RunSuite(t, new(TestRunningDemoSuite))
42 | }
43 |
--------------------------------------------------------------------------------
/examples/suite_demo/setup_test.go:
--------------------------------------------------------------------------------
1 | //go:build examples_new
2 | // +build examples_new
3 |
4 | package suite_demo
5 |
6 | import (
7 | "context"
8 | "fmt"
9 | "testing"
10 |
11 | "github.com/jackc/fake"
12 | "github.com/ozontech/allure-go/pkg/allure"
13 | "github.com/ozontech/allure-go/pkg/framework/provider"
14 | "github.com/ozontech/allure-go/pkg/framework/suite"
15 | )
16 |
17 | type Example struct {
18 | country string
19 | number int
20 | }
21 |
22 | func (e *Example) String() string {
23 | return fmt.Sprintf("%s#%d", e.country, e.number)
24 | }
25 |
26 | type SetupSuite struct {
27 | suite.Suite
28 | ParamMyTest []*Example
29 | }
30 |
31 | func (s *SetupSuite) BeforeAll(t provider.T) {
32 | var params []*allure.Parameter
33 | for i := 0; i < 10; i++ {
34 | param := &Example{
35 | country: fake.Country(),
36 | number: fake.Year(1900, 2000),
37 | }
38 | params = append(params, allure.NewParameter(fmt.Sprintf("Ex %d", i), param))
39 | s.ParamMyTest = append(s.ParamMyTest, param)
40 | }
41 | t.NewStep("BeforeAllStep", params...)
42 | }
43 |
44 | func (s *SetupSuite) BeforeEach(t provider.T) {
45 | t.Epic("Demo")
46 | t.Feature("BeforeAfter")
47 | t.NewStep("This Step will be before Each")
48 | }
49 |
50 | func (s *SetupSuite) AfterEach(t provider.T) {
51 | t.NewStep("AfterEach Step")
52 | }
53 |
54 | func (s *SetupSuite) AfterAll(t provider.T) {
55 | t.NewStep("AfterAll Step")
56 | }
57 |
58 | func (s *SetupSuite) TableTestMyTest(t provider.T, example *Example) {
59 | t.Titlef("TableTest With Setup - %s", example)
60 | t.Descriptionf(`
61 | Test will unpack all data from passed parameter to the variables in WithTestSetup func.
62 | After test finish, it will do ctx.Done() in TestTearDown.
63 | All Setup and TearDown tests will be add as Befores and Afters to test's container.
64 | Used Data: %s`, example)
65 | t.Tags("Parametrized", "Parallel", "Setup", "BeforeAfter")
66 |
67 | t.Parallel()
68 | var (
69 | country string
70 | year int
71 | ctx context.Context
72 | )
73 |
74 | defer t.WithTestTeardown(func(t provider.T) {
75 | t.WithNewStep("Close ctx", func(sCtx provider.StepCtx) {
76 | ctx.Done()
77 | sCtx.WithNewParameters("ctx", ctx)
78 | })
79 | })
80 |
81 | t.WithTestSetup(func(t provider.T) {
82 | t.WithNewStep("init country", func(sCtx provider.StepCtx) {
83 | country = example.country
84 | sCtx.WithNewParameters("country", country)
85 | })
86 | t.WithNewStep("init year", func(sCtx provider.StepCtx) {
87 | year = example.number
88 | sCtx.WithNewParameters("year", year)
89 | })
90 | t.WithNewStep("init ctx", func(sCtx provider.StepCtx) {
91 | ctx = context.Background()
92 | sCtx.WithNewParameters("ctx", ctx)
93 | })
94 | })
95 |
96 | t.Require().NotEqual("PonyCountry", country, "No magic countries in the list")
97 | t.Require().NotEqual(2007, year, "No one returned to 2007")
98 | t.Require().NotNil(ctx, "Not empty context")
99 | }
100 |
101 | func (s *SetupSuite) TestMyOtherTest(t provider.T) {
102 | t.Title("Just Test WithSetup")
103 | t.Description(`
104 | Test will prepare some data at TestSetup.`)
105 | t.Tags("Parallel", "Setup", "BeforeAfter")
106 |
107 | t.Parallel()
108 | var (
109 | name string
110 | age int
111 | )
112 |
113 | t.WithTestSetup(func(t provider.T) {
114 | t.WithNewStep("init args", func(sCtx provider.StepCtx) {
115 | name = fake.FullName()
116 | age = fake.Day()
117 | sCtx.WithNewParameters("name", name, "age", age)
118 | })
119 | })
120 | }
121 |
122 | func TestRunner(t *testing.T) {
123 | suite.RunSuite(t, new(SetupSuite))
124 | }
125 |
--------------------------------------------------------------------------------
/examples/suite_demo/skip_test.go:
--------------------------------------------------------------------------------
1 | //go:build examples_new
2 | // +build examples_new
3 |
4 | package suite_demo
5 |
6 | import (
7 | "testing"
8 |
9 | "github.com/ozontech/allure-go/pkg/framework/provider"
10 | "github.com/ozontech/allure-go/pkg/framework/suite"
11 | )
12 |
13 | type SkipDemoSuite struct {
14 | suite.Suite
15 | }
16 |
17 | func (s *SkipDemoSuite) TestSkip(t provider.T) {
18 | t.Epic("Demo")
19 | t.Feature("Skip Test")
20 | t.Title("Skip test")
21 | t.Description(`
22 | This test will be skipped`)
23 |
24 | t.Tags("Test", "Skip")
25 | t.Skip("Skip Reason")
26 | }
27 |
28 | func TestSkipDemo(t *testing.T) {
29 | t.Parallel()
30 | suite.RunSuite(t, new(SkipDemoSuite))
31 | }
32 |
--------------------------------------------------------------------------------
/examples/suite_demo/step_test.go:
--------------------------------------------------------------------------------
1 | //go:build examples_new
2 | // +build examples_new
3 |
4 | package suite_demo
5 |
6 | import (
7 | "testing"
8 | "time"
9 |
10 | "github.com/ozontech/allure-go/pkg/allure"
11 | "github.com/ozontech/allure-go/pkg/framework/provider"
12 | "github.com/ozontech/allure-go/pkg/framework/suite"
13 | )
14 |
15 | type StepDemoSuite struct {
16 | suite.Suite
17 | }
18 |
19 | func (s *StepDemoSuite) TestAddSteps(t provider.T) {
20 | t.Epic("Demo")
21 | t.Feature("Steps")
22 | t.Title("Base. Add steps to allure result")
23 | t.Description(`
24 | Step A, Step B and Step C will be add to Allure Result`)
25 |
26 | t.Tags("Steps")
27 |
28 | stepA := allure.NewSimpleStep("Step A")
29 | t.Step(stepA)
30 |
31 | stepB := allure.NewStep("Step B", // Step's Name
32 | allure.Passed, // Step Status
33 | allure.GetNow(), // Step Start
34 | allure.GetNow(), // Step Finish
35 | allure.NewParameters("paramB", "value")) // Step Parameters
36 |
37 | t.Step(stepB)
38 |
39 | stepC := allure.NewSimpleStep("Step C")
40 | stepC.Start = allure.GetNow()
41 | stepC.WithNewParameters("paramC", "value")
42 | stepC.Stop = allure.GetNow()
43 | t.Step(stepC)
44 | }
45 |
46 | func (s *StepDemoSuite) TestQuickWorkWithSteps(t provider.T) {
47 | t.Epic("Demo")
48 | t.Feature("Steps")
49 | t.Title("Base. Add steps to allure result")
50 | t.Description(`
51 | Step A, Step B, Step C and Step D will be add to Allure Result`)
52 |
53 | t.Tags("Steps")
54 |
55 | t.Step(allure.NewSimpleStep("Step A").Passed()) // This step will be passed
56 | t.Step(allure.NewSimpleStep("Step B").Failed()) // This step will be failed
57 | t.Step(allure.NewSimpleStep("Step C").Skipped()) // This step will be skipped
58 |
59 | stepD := allure.NewSimpleStep("Step D").Begin()
60 | time.Sleep(1 * time.Second) // Do some
61 | stepD = stepD.Finish().Passed()
62 | t.Step(stepD)
63 | }
64 |
65 | func (s *StepDemoSuite) TestInnerStep(t provider.T) {
66 | t.Epic("Demo")
67 | t.Layer("Layer")
68 | t.Feature("Steps")
69 | t.Title("Add child steps to existed step.")
70 | t.Description(`
71 | Step A is parent step for Step B and Step C
72 | Step D is parent step for Step E and Step F
73 | Call order will be saved in allure report
74 | A -> (B, C), D -> (E, F)`)
75 |
76 | t.Tags("Steps", "Nesting")
77 |
78 | // use allure.NewSimpleStep constructor
79 | stepA := allure.NewSimpleStep("Step A")
80 | stepB := allure.NewSimpleStep("Step B")
81 | stepC := allure.NewSimpleStep("Step C")
82 | stepA.WithChild(stepB)
83 | stepA.WithChild(stepC)
84 | t.Step(stepA)
85 |
86 | // use InnerStep function
87 | stepD := allure.NewSimpleStep("Step D")
88 | t.Step(stepD)
89 | stepD.WithChild(allure.NewSimpleStep("Step E"))
90 | stepF := allure.NewStep("Step F", // Step's Name
91 | allure.Passed, // Step Status
92 | allure.GetNow(), // Step Start
93 | allure.GetNow(), // Step Finish
94 | allure.NewParameters("paramF", "value")) // Step Parameters
95 | stepF.WithParent(stepD)
96 |
97 | // forward way
98 | stepG := allure.NewSimpleStep("Step G")
99 | stepH := allure.NewSimpleStep("Step H")
100 | stepI := allure.NewSimpleStep("Step I")
101 | stepG.WithChild(stepH)
102 | stepG.WithChild(stepI)
103 | }
104 |
105 | func TestStepDemo(t *testing.T) {
106 | t.Parallel()
107 | suite.RunSuite(t, new(StepDemoSuite))
108 | }
109 |
--------------------------------------------------------------------------------
/examples/suite_demo/step_tree_test.go:
--------------------------------------------------------------------------------
1 | //go:build examples_new
2 | // +build examples_new
3 |
4 | package suite_demo
5 |
6 | import (
7 | "testing"
8 |
9 | "github.com/ozontech/allure-go/pkg/framework/provider"
10 | "github.com/ozontech/allure-go/pkg/framework/suite"
11 | )
12 |
13 | type StepTreeDemoSuite struct {
14 | suite.Suite
15 | }
16 |
17 | func (s *StepTreeDemoSuite) TestInnerSteps(t provider.T) {
18 | t.Epic("Demo")
19 | t.Feature("Inner Steps")
20 | t.Title("Simple Nesting")
21 | t.Description(`
22 | Step A is parent step for Step B and Step C
23 | Call order will be saved in allure report
24 | A -> (B, C)`)
25 |
26 | t.Tags("Steps", "Nesting")
27 |
28 | t.WithNewStep("Step A", func(ctx provider.StepCtx) {
29 | ctx.NewStep("Step B")
30 | ctx.NewStep("Step C")
31 | })
32 | }
33 |
34 | func (s *StepTreeDemoSuite) TestComplexStepTree(t provider.T) {
35 | t.Epic("Demo")
36 | t.Feature("Inner Steps")
37 | t.Title("Complex Nesting")
38 | t.Description(`
39 | Step A is parent for Step B, Step C and Step F
40 | Step C is parent for Step D and Step E
41 | Step F is parent for Step G and Step H
42 | Call order will be saved in allure report
43 | A -> (B, C -> (D, E), F -> (G, H), I)`)
44 |
45 | t.Tags("Steps", "Nesting")
46 |
47 | t.WithNewStep("Step A", func(ctx provider.StepCtx) {
48 | ctx.NewStep("Step B")
49 | ctx.WithNewStep("Step C", func(ctx provider.StepCtx) {
50 | ctx.NewStep("Step D")
51 | ctx.NewStep("Step E")
52 | })
53 | ctx.WithNewStep("Step F", func(ctx provider.StepCtx) {
54 | ctx.NewStep("Step G")
55 | ctx.NewStep("Step H")
56 | })
57 | ctx.NewStep("Step I")
58 | })
59 | }
60 |
61 | func TestStepTree(t *testing.T) {
62 | t.Parallel()
63 | suite.RunSuite(t, new(StepTreeDemoSuite))
64 | }
65 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/ozontech/allure-go
2 |
3 | go 1.17
4 |
5 | replace (
6 | github.com/ozontech/allure-go/pkg/allure => ./pkg/allure
7 | github.com/ozontech/allure-go/pkg/framework => ./pkg/framework
8 | )
9 |
10 | require (
11 | github.com/jackc/fake v0.0.0-20150926172116-812a484cc733
12 | github.com/ozontech/allure-go/pkg/allure v0.6.14
13 | github.com/ozontech/allure-go/pkg/framework v0.6.33
14 | )
15 |
16 | require (
17 | github.com/davecgh/go-spew v1.1.1 // indirect
18 | github.com/google/uuid v1.3.0 // indirect
19 | github.com/pkg/errors v0.9.1 // indirect
20 | github.com/pmezard/go-difflib v1.0.0 // indirect
21 | github.com/stretchr/testify v1.7.1 // indirect
22 | gopkg.in/yaml.v3 v3.0.0 // indirect
23 | )
24 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
5 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
6 | github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc=
7 | github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
8 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
9 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
10 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
11 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
12 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
13 | github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
14 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
15 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
16 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
17 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
18 | gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
19 | gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
20 |
--------------------------------------------------------------------------------
/pkg/allure/.golangci.yaml:
--------------------------------------------------------------------------------
1 | # More info on config here: https://github.com/golangci/golangci-lint#config-file
2 | run:
3 | deadline: 10s
4 | timeout: 5m
5 | issues-exit-code: 1
6 | tests: true
7 | skip-dirs:
8 | - bin
9 | - vendor
10 | - var
11 | - tmp
12 | skip-files:
13 | - \.pb\.go$
14 | - \.pb\.goclay\.go$
15 | - \_test.go$
16 |
17 | output:
18 | format: colored-line-number
19 | print-issued-lines: true
20 | print-linter-name: true
21 |
22 | linters-settings:
23 | govet:
24 | check-shadowing: true
25 | golint:
26 | min-confidence: 0
27 | dupl:
28 | threshold: 100
29 | goconst:
30 | min-len: 2
31 | min-occurrences: 2
32 |
33 | linters:
34 | disable-all: true
35 | enable:
36 | - golint
37 | - govet
38 | - errcheck
39 | - deadcode
40 | - structcheck
41 | - varcheck
42 | - ineffassign
43 | - typecheck
44 | - dupl
45 | - goconst
46 | - gosec
47 | - goimports
48 | - megacheck
49 |
50 |
51 | issues:
52 | exclude-use-default: false
53 | exclude:
54 | # _ instead of err checks
55 | - G104
56 | - G306
57 | # md5 using for hash generation, not for security, so ignore this
58 | - G401
59 | - G501
60 | # for "public interface + private struct implementation" cases only!
61 | - exported func * returns unexported type *, which can be annoying to use
62 | # can be removed in the development phase
63 | # - (comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)
64 | # not for the active development - can be removed in the stable phase
65 | - should have a package comment, unless it's in another file for this package
66 | - don't use an underscore in package name
67 | # errcheck: Almost all programs ignore errors on these functions and in most cases it's ok
68 | - Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv|.*Rollback). is not checked
69 | - should check returned error before deferring
70 | - should have comment or be unexported
71 | - a blank import should be only in a main or test package
72 | - Can't process result by diff processor
73 |
--------------------------------------------------------------------------------
/pkg/allure/Makefile:
--------------------------------------------------------------------------------
1 | APP?=allure-testify
2 | RELEASE?=0.5.0
3 | GOOS?=darwin
4 |
5 | COMMIT?=$(shell git rev-parse --short HEAD)
6 | BUILD_TIME?=$(shell date -u '+%Y-%m-%d_%H:%M:%S')
7 |
8 | export GO111MODULE=on
9 | export GOSUMDB=off
10 | LOCAL_BIN:=$(CURDIR)/bin
11 |
12 | ##################### GOLANG-CI RELATED CHECKS #####################
13 | # Check global GOLANGCI-LINT
14 | GOLANGCI_BIN:=$(LOCAL_BIN)/golangci-lint
15 | GOLANGCI_TAG:=1.38.0
16 |
17 | # Check local bin version
18 | ifneq ($(wildcard $(GOLANGCI_BIN)),)
19 | GOLANGCI_BIN_VERSION:=$(shell $(GOLANGCI_BIN) --version)
20 | ifneq ($(GOLANGCI_BIN_VERSION),)
21 | GOLANGCI_BIN_VERSION_SHORT:=$(shell echo "$(GOLANGCI_BIN_VERSION)" | sed -E 's/.* version (.*) built from .* on .*/\1/g')
22 | else
23 | GOLANGCI_BIN_VERSION_SHORT:=0
24 | endif
25 | ifneq "$(GOLANGCI_TAG)" "$(word 1, $(sort $(GOLANGCI_TAG) $(GOLANGCI_BIN_VERSION_SHORT)))"
26 | GOLANGCI_BIN:=
27 | endif
28 | endif
29 |
30 | # Check global bin version
31 | ifneq (, $(shell which golangci-lint))
32 | GOLANGCI_VERSION:=$(shell golangci-lint --version 2> /dev/null )
33 | ifneq ($(GOLANGCI_VERSION),)
34 | GOLANGCI_VERSION_SHORT:=$(shell echo "$(GOLANGCI_VERSION)"|sed -E 's/.* version (.*) built from .* on .*/\1/g')
35 | else
36 | GOLANGCI_VERSION_SHORT:=0
37 | endif
38 | ifeq "$(GOLANGCI_TAG)" "$(word 1, $(sort $(GOLANGCI_TAG) $(GOLANGCI_VERSION_SHORT)))"
39 | GOLANGCI_BIN:=$(shell which golangci-lint)
40 | endif
41 | endif
42 | ##################### GOLANG-CI RELATED CHECKS #####################
43 |
44 | # run full lint like in pipeline
45 | .PHONY: lint
46 | lint: install-lint
47 | $(GOLANGCI_BIN) run --config=.golangci.yaml ./...
48 |
49 |
50 | .PHONY: install-lint
51 | install-lint:
52 | ifeq ($(wildcard $(GOLANGCI_BIN)),)
53 | $(info #Downloading golangci-lint v$(GOLANGCI_TAG))
54 | tmp=$$(mktemp -d) && cd $$tmp && pwd && go mod init temp && go get -d github.com/golangci/golangci-lint/cmd/golangci-lint@v$(GOLANGCI_TAG) && \
55 | go build -ldflags "-X 'main.version=$(GOLANGCI_TAG)' -X 'main.commit=test' -X 'main.date=test'" -o $(LOCAL_BIN)/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint && \
56 | rm -rf $$tmp
57 | GOLANGCI_BIN:=$(LOCAL_BIN)/golangci-lint
58 | endif
59 |
60 | .PHONY: test
61 | test:
62 | go test ./... -cover
--------------------------------------------------------------------------------
/pkg/allure/attachment.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "github.com/google/uuid"
5 | )
6 |
7 | // Attachment - is an implementation of the attachments to the report in allure. It is most often used to contain
8 | // screenshots, responses, files and other data obtained during the test.
9 | type Attachment struct {
10 | Name string `json:"name,omitempty"` // Attachment name
11 | Source string `json:"source,omitempty"` // Path to the Attachment file (name)
12 | Type MimeType `json:"type,omitempty"` // Mime-type of the Attachment
13 | uuid string // Unique identifier of the Attachment
14 | content []byte // Attachment's content as bytes array
15 | }
16 |
17 | // MimeType is Attachment's mime type.
18 | // See more: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
19 | type MimeType string
20 |
21 | // Attachment's MimeType constants
22 | const (
23 | Text MimeType = "text/plain"
24 | Csv MimeType = "text/csv"
25 | Tsv MimeType = "text/tab-separated-values"
26 | URIList MimeType = "text/uri-list"
27 |
28 | HTML MimeType = "text/html"
29 | XML MimeType = "application/xml"
30 | JSON MimeType = "application/json"
31 | Yaml MimeType = "application/yaml"
32 | Pcap MimeType = "application/vnd.tcpdump.pcap"
33 |
34 | Png MimeType = "image/png"
35 | Jpg MimeType = "image/jpg"
36 | Svg MimeType = "image/svg-xml"
37 | Gif MimeType = "image/gif"
38 | Bmp MimeType = "image/bmp"
39 | Tiff MimeType = "image/tiff"
40 |
41 | Mp4 MimeType = "video/mp4"
42 | Ogg MimeType = "video/ogg"
43 | Webm MimeType = "video/webm"
44 | Mpeg MimeType = "video/mpeg"
45 |
46 | Pdf MimeType = "application/pdf"
47 | Xlsx MimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
48 | )
49 |
50 | // Ext returns file extension for this mime-type
51 | func (mt MimeType) Ext() string {
52 | switch mt {
53 | case Text:
54 | return ".txt"
55 | case Csv:
56 | return ".csv"
57 | case Tsv:
58 | return ".tsv"
59 | case URIList:
60 | return ".uri"
61 | case HTML:
62 | return ".html"
63 | case XML:
64 | return ".xml"
65 | case JSON:
66 | return ".json"
67 | case Yaml:
68 | return ".yaml"
69 | case Pcap:
70 | return ".pcap"
71 | case Png:
72 | return ".png"
73 | case Jpg:
74 | return ".jpg"
75 | case Svg:
76 | return ".svg"
77 | case Gif:
78 | return ".gif"
79 | case Bmp:
80 | return ".bmp"
81 | case Tiff:
82 | return ".tiff"
83 | case Mp4:
84 | return ".mp4"
85 | case Ogg:
86 | return ".ogg"
87 | case Webm:
88 | return ".webm"
89 | case Mpeg:
90 | return ".mpeg"
91 | case Pdf:
92 | return ".pdf"
93 | case Xlsx:
94 | return ".xlsx"
95 | default:
96 | return ""
97 | }
98 | }
99 |
100 | // NewAttachment - Constructor. Returns pointer to new attachment object.
101 | func NewAttachment(name string, mimeType MimeType, content []byte) *Attachment {
102 | id := uuid.New().String()
103 |
104 | return &Attachment{
105 | uuid: id,
106 | content: content,
107 | Name: name,
108 | Type: mimeType,
109 | Source: id + "-attachment" + mimeType.Ext(),
110 | }
111 | }
112 |
113 | func (a *Attachment) GetUUID() string {
114 | return a.uuid
115 | }
116 |
117 | func (a *Attachment) GetContent() []byte {
118 | return a.content
119 | }
120 |
121 | // Print - Creates a file from `Attachment.content`. The file type is determined by its `Attachment.mimeType`.
122 | func (a *Attachment) Print() error {
123 | return NewFileManager().CreateFile(a.Source, a.content)
124 | }
125 |
--------------------------------------------------------------------------------
/pkg/allure/attachment_test.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "testing"
7 |
8 | "github.com/stretchr/testify/require"
9 | )
10 |
11 | var mimeTypes = []MimeType{
12 | Text,
13 | Csv,
14 | Tsv,
15 | URIList,
16 | HTML,
17 | XML,
18 | JSON,
19 | Yaml,
20 | Pcap,
21 | Png,
22 | Jpg,
23 | Svg,
24 | Gif,
25 | Bmp,
26 | Tiff,
27 | Mp4,
28 | Ogg,
29 | Webm,
30 | Mpeg,
31 | Pdf,
32 | Xlsx,
33 | }
34 |
35 | func TestNewAttachment(t *testing.T) {
36 | for _, mt := range mimeTypes {
37 | testAttachName := fmt.Sprintf("Test init fileType: %s", mt)
38 | t.Run(testAttachName, func(t *testing.T) {
39 | content := []byte("some content")
40 | attachment := NewAttachment(testAttachName, mt, content)
41 | require.NotNil(t, attachment.uuid)
42 | require.Equal(t, mt, attachment.Type, "mime type should be same")
43 | require.Equal(t, testAttachName, attachment.Name)
44 | require.Equal(t, content, attachment.content)
45 | require.Contains(t, attachment.Source, mt.Ext())
46 | })
47 | }
48 | }
49 |
50 | func TestAttachment_Print(t *testing.T) {
51 | const testFolder = "allure-results"
52 |
53 | err := os.MkdirAll(testFolder, os.ModePerm)
54 | require.NoError(t, err)
55 |
56 | defer os.RemoveAll(testFolder)
57 |
58 | for _, mt := range mimeTypes {
59 | testAttachName := fmt.Sprintf("Test init fileType: %s", mt)
60 | t.Run(testAttachName, func(t *testing.T) {
61 | content := []byte("some content")
62 | attachment := NewAttachment(testAttachName, mt, content)
63 | err := attachment.Print()
64 | require.Nil(t, err, "No errors expected")
65 | require.FileExists(t, fmt.Sprintf("./allure-results/%s", attachment.Source))
66 | })
67 | }
68 | }
69 |
70 | func TestAttachment_GetUUID(t *testing.T) {
71 | content := []byte("some content")
72 | testAttachName := fmt.Sprintf("Test init fileType: %s", Text)
73 |
74 | attachment := NewAttachment(testAttachName, Text, content)
75 | require.NotNil(t, attachment.GetUUID())
76 | }
77 |
78 | func TestAttachment_GetContent(t *testing.T) {
79 | content := []byte("some content")
80 | testAttachName := fmt.Sprintf("Test init fileType: %s", Text)
81 |
82 | attachment := NewAttachment(testAttachName, Text, content)
83 | require.Equal(t, content, attachment.GetContent())
84 | }
85 |
--------------------------------------------------------------------------------
/pkg/allure/config.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | // DefaultVersion - allure-go current Version
4 | const DefaultVersion = "Allure-Go@v0.6.0"
5 |
6 | const (
7 | resultsPathEnvKey = "ALLURE_OUTPUT_PATH" // Indicates the path to the results print folder
8 | outputFolderEnvKey = "ALLURE_OUTPUT_FOLDER" // Indicates the name of the folder to print the results.
9 | issuePatternEnvKey = "ALLURE_ISSUE_PATTERN" // Indicates the URL pattern for Issue. It must contain exactly one `%s`
10 | testCasePatternEnvKey = "ALLURE_TESTCASE_PATTERN" // Indicates the URL pattern for TestCase. It must contain exactly one `%s`
11 | tmsLinkPatternEnvKey = "ALLURE_LINK_TMS_PATTERN" // Indicates the URL pattern for TmsLink. It must contain exactly one `%s`
12 | defaultTagsEnvKey = "ALLURE_LAUNCH_TAGS" // Indicates the default tags that will mark all tests in the run. The tags must be specified separated by commas.
13 | )
14 |
15 | // Attachment permission
16 | const fileSystemPermissionCode = 0o644
17 |
--------------------------------------------------------------------------------
/pkg/allure/config_test.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/require"
7 | )
8 |
9 | func TestConfig(t *testing.T) {
10 | require.Equal(t, "ALLURE_OUTPUT_PATH", resultsPathEnvKey)
11 | require.Equal(t, "ALLURE_OUTPUT_FOLDER", outputFolderEnvKey)
12 | require.Equal(t, "ALLURE_ISSUE_PATTERN", issuePatternEnvKey)
13 | require.Equal(t, "ALLURE_TESTCASE_PATTERN", testCasePatternEnvKey)
14 | require.Equal(t, "ALLURE_LAUNCH_TAGS", defaultTagsEnvKey)
15 | require.Equal(t, "ALLURE_LINK_TMS_PATTERN", tmsLinkPatternEnvKey)
16 | require.Equal(t, 0o644, fileSystemPermissionCode)
17 | }
18 |
--------------------------------------------------------------------------------
/pkg/allure/container.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "encoding/json"
5 |
6 | "github.com/google/uuid"
7 | "github.com/pkg/errors"
8 | )
9 |
10 | // Container This is an implementation of the `Container` entity used by Allure to handle TestSetup and TestTeardown hooks.
11 | // The list of container-dependent tests is contained in the `Container.Children` array.
12 | // Note: For Before/After Test hooks, the Container.Children array will contain one element (one container per test).
13 | // For Before/After Suite hooks the Container.Children array will contain UUIDs of all tests for which the hook was executed.
14 | type Container struct {
15 | UUID uuid.UUID `json:"uuid,omitempty"` // Unique identifier of the container
16 | Children []uuid.UUID `json:"children,omitempty"` // UUID array containing all reports referring to the container
17 | Befores []*Step `json:"befores,omitempty"` // Array of pointers to allure.Step in Test Setup
18 | Afters []*Step `json:"afters,omitempty"` // Array of pointers to allure.Step in Test TearDown
19 | Start int64 `json:"start,omitempty"` // Start time of the container
20 | Stop int64 `json:"stop,omitempty"` // Stop time of the container
21 | }
22 |
23 | // NewContainer - Constructor. Builds and returns a new `allure.Container` object.
24 | func NewContainer() *Container {
25 | return &Container{
26 | UUID: uuid.New(),
27 | }
28 | }
29 |
30 | // AddChild Adds a new child to the Container.Children array.
31 | func (container *Container) AddChild(child uuid.UUID) {
32 | container.Children = append(container.Children, child)
33 | }
34 |
35 | // IsEmpty Returns `true` if arrays Container.Befores and Container.Afters are empty.
36 | func (container *Container) IsEmpty() bool {
37 | return len(container.Befores) == 0 && len(container.Afters) == 0
38 | }
39 |
40 | // Print Checks the file with the function Container.IsEmpty:
41 | //
42 | // 1. If the container is empty, execution of the function completes without error.
43 | //
44 | // 2. If the container contains steps
45 | // 2.1. Call Container.PrintAttachments()
46 | // 2.2. Serializes the file into `uuid4-container.json`.
47 | // 2.3. Creates a file in the file system in the output folder (`$ALLURE_OUTPUT_PATH`/`$ALLURE_OUTPUT_FOLDER`). If there is an error during
48 | //
49 | // If error occurs during execution - returns it
50 | func (container *Container) Print() error {
51 | if !container.IsEmpty() {
52 | container.PrintAttachments()
53 |
54 | return container.printContainer()
55 | }
56 |
57 | return nil
58 | }
59 |
60 | // PrintAttachments It goes through all Container.Befores and Container.Afters
61 | // of the Container and calls the Container.PrintAttachments() method at each allure.Step.
62 | func (container *Container) PrintAttachments() {
63 | for _, step := range container.Befores {
64 | step.PrintAttachments()
65 | }
66 |
67 | for _, step := range container.Afters {
68 | step.PrintAttachments()
69 | }
70 | }
71 |
72 | // Begin Sets `Container.Start` = allure.GetNow()
73 | func (container *Container) Begin() {
74 | container.Start = GetNow()
75 | }
76 |
77 | // Finish Sets Container.Stop = allure.GetNow()
78 | func (container *Container) Finish() {
79 | container.Stop = GetNow()
80 | }
81 |
82 | // Done calls Finish and Print
83 | func (container *Container) Done() error {
84 | container.Finish()
85 |
86 | return container.Print()
87 | }
88 |
89 | // ToJSON marshal allure.Result to json file
90 | //
91 | // Deprecated: use [json.Marshal] instead
92 | func (container *Container) ToJSON() ([]byte, error) {
93 | return json.Marshal(container)
94 | }
95 |
96 | // Print prints all attachments of [Container.Befores] and [Container.Afters]
97 | // after that marshals [Container] and [os.WriteFile]
98 | func (container *Container) printContainer() error {
99 | bResult, err := json.Marshal(container)
100 | if err != nil {
101 | return errors.Wrap(err, "Failed marshal Result")
102 | }
103 |
104 | err = NewFileManager().CreateFile(container.UUID.String()+"-container.json", bResult)
105 | if err != nil {
106 | return errors.Wrap(err, "Error write Result")
107 | }
108 |
109 | return nil
110 | }
111 |
--------------------------------------------------------------------------------
/pkg/allure/container_test.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "io"
7 | "os"
8 | "testing"
9 | "time"
10 |
11 | "github.com/stretchr/testify/assert"
12 | "github.com/stretchr/testify/require"
13 | )
14 |
15 | const (
16 | allureDir = "allure-results"
17 | )
18 |
19 | func TestNewContainer(t *testing.T) {
20 | container := NewContainer()
21 | require.NotNil(t, container)
22 | require.Zero(t, container.Start)
23 | require.Zero(t, container.Stop)
24 | require.NotNil(t, container.UUID)
25 | }
26 |
27 | func TestContainer_AddChild(t *testing.T) {
28 | container := NewContainer()
29 | result := NewResult("Mock Name", "Full Mock Name")
30 | container.AddChild(result.UUID)
31 | require.NotEmpty(t, container.Children)
32 | require.Len(t, container.Children, 1)
33 | require.Equal(t, result.UUID, container.Children[0])
34 | }
35 |
36 | func TestContainer_Begin(t *testing.T) {
37 | container := NewContainer()
38 | begin := GetNow()
39 | container.Begin()
40 | assert.Equal(t, container.Start, begin)
41 | }
42 |
43 | func TestContainer_Finish(t *testing.T) {
44 | container := NewContainer()
45 | finish := GetNow()
46 | container.Finish()
47 | assert.Equal(t, container.Stop, finish)
48 | }
49 |
50 | func TestContainer_Print(t *testing.T) {
51 | container := NewContainer()
52 | containerBefore := NewSimpleStep("Before")
53 | containerAfter := NewSimpleStep("After")
54 | container.Befores = append(container.Befores, containerBefore)
55 | container.Afters = append(container.Afters, containerAfter)
56 |
57 | _ = container.Print()
58 | defer os.RemoveAll(allureDir)
59 | require.DirExists(t, allureDir)
60 | files, _ := os.ReadDir(allureDir)
61 | require.Len(t, files, 1)
62 | var jsonFile *os.File
63 | defer jsonFile.Close()
64 |
65 | f := files[0]
66 | emptyContainer := &Container{}
67 | jsonFile, _ = os.Open(fmt.Sprintf("%s/%s", allureDir, f.Name()))
68 | bytes, readErr := io.ReadAll(jsonFile)
69 | require.NoError(t, readErr)
70 | unMarshallErr := json.Unmarshal(bytes, emptyContainer)
71 | require.NoError(t, unMarshallErr)
72 | require.Equal(t, container.UUID, emptyContainer.UUID)
73 |
74 | require.NotEmpty(t, emptyContainer.Befores)
75 | require.NotEmpty(t, emptyContainer.Afters)
76 | require.Len(t, emptyContainer.Befores, 1)
77 | require.Len(t, emptyContainer.Afters, 1)
78 |
79 | before := emptyContainer.Befores[0]
80 | after := emptyContainer.Afters[0]
81 |
82 | require.Equal(t, containerBefore, before)
83 | require.Equal(t, containerAfter, after)
84 | }
85 |
86 | func TestMarshallingContainer(t *testing.T) {
87 | container := NewContainer()
88 | b := `grpc_cli call --json_input --json_output myendpoint.com:82 bla.bla/GetBla '{"bla":"blabla"}' -metadata 'x-bla::x-app-bla:bla-qa/bla-tests:x-bla-version::x-nocache:true:x-pf-nocache:true:x-s2s:*****'`
89 | container.Befores = append(container.Befores, &Step{
90 | Name: "name",
91 | Status: Passed,
92 | Attachments: nil,
93 | Start: time.Now().UnixNano(),
94 | Stop: time.Now().UnixNano(),
95 | Steps: nil,
96 | Parameters: []*Parameter{NewParameter("p", b)},
97 | })
98 |
99 | _, err := container.ToJSON()
100 | require.NoError(t, err)
101 | }
102 |
--------------------------------------------------------------------------------
/pkg/allure/errors.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "strings"
5 | )
6 |
7 | // Copied from https://cs.opensource.google/go/go/+/refs/tags/go1.24.3:src/errors/join.go;l=40
8 | // Since this go version does not have errors.Join
9 | //
10 | // TODO: delete this in v2
11 | type joinError struct {
12 | errs []error
13 | }
14 |
15 | func (e *joinError) Error() string {
16 | b := make([]string, 0, len(e.errs))
17 |
18 | for _, err := range e.errs {
19 | b = append(b, err.Error())
20 | }
21 |
22 | return strings.Join(b, "\n")
23 | }
24 |
25 | func (e *joinError) Unwrap() []error {
26 | return e.errs
27 | }
28 |
--------------------------------------------------------------------------------
/pkg/allure/file_manager.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 | )
7 |
8 | type FileManager interface {
9 | CreateFile(name string, content []byte) error
10 | }
11 |
12 | type fileManager struct {
13 | resultsPath string
14 | }
15 |
16 | func NewFileManager() FileManager {
17 | resultsPath := getResultPath()
18 |
19 | fm := &fileManager{resultsPath: resultsPath}
20 | fm.createOutputDir()
21 |
22 | return fm
23 | }
24 |
25 | func (m *fileManager) CreateFile(name string, content []byte) error {
26 | file := filepath.Join(m.resultsPath, name)
27 |
28 | return os.WriteFile(file, content, fileSystemPermissionCode)
29 | }
30 |
31 | func (m *fileManager) createOutputDir() {
32 | isExists, err := exists(m.resultsPath)
33 | if err != nil {
34 | panic(err)
35 | }
36 |
37 | if !isExists {
38 | _ = os.MkdirAll(m.resultsPath, os.ModePerm)
39 | }
40 | }
41 |
42 | func getOutputFolderName() string {
43 | outputFolderName := os.Getenv(outputFolderEnvKey)
44 | if outputFolderName != "" {
45 | return outputFolderName
46 | }
47 |
48 | return "allure-results"
49 | }
50 |
51 | func getResultPath() string {
52 | resultsPathToOutput := os.Getenv(resultsPathEnvKey)
53 | outputFolderName := getOutputFolderName()
54 |
55 | if resultsPathToOutput != "" {
56 | return filepath.Join(resultsPathToOutput, outputFolderName)
57 | }
58 |
59 | return outputFolderName
60 | }
61 |
62 | // exists returns whether the given file or directory exists
63 | func exists(path string) (bool, error) {
64 | _, err := os.Stat(path)
65 | if err == nil {
66 | return true, nil
67 | }
68 |
69 | if os.IsNotExist(err) {
70 | return false, nil
71 | }
72 |
73 | return false, err
74 | }
75 |
--------------------------------------------------------------------------------
/pkg/allure/file_manager_test.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "os"
7 | "testing"
8 |
9 | "github.com/stretchr/testify/require"
10 | )
11 |
12 | func TestNewFileManager(t *testing.T) {
13 | fm := NewFileManager()
14 | require.NotNil(t, fm)
15 | }
16 |
17 | func TestCreateOutputDir(t *testing.T) {
18 | fm := &fileManager{allureDir}
19 | fm.createOutputDir()
20 | defer os.RemoveAll(allureDir)
21 | require.DirExists(t, allureDir)
22 | }
23 |
24 | func TestGetOutputFolderName_noEnv(t *testing.T) {
25 | require.Equal(t, "allure-results", getOutputFolderName())
26 | }
27 |
28 | func TestGetOutputFolderName_Env(t *testing.T) {
29 | os.Setenv(outputFolderEnvKey, "not_allure_results")
30 | defer os.Setenv(outputFolderEnvKey, "")
31 | require.Equal(t, "not_allure_results", getOutputFolderName())
32 | }
33 |
34 | func TestGetResultPath_noEnv(t *testing.T) {
35 | require.Equal(t, allureDir, getResultPath())
36 | }
37 |
38 | func TestGetResultPath_Env(t *testing.T) {
39 | os.Setenv(resultsPathEnvKey, "not_allure_results")
40 | defer os.Setenv(resultsPathEnvKey, "")
41 | require.Equal(t, "not_allure_results/allure-results", getResultPath())
42 | }
43 |
44 | func TestFileManager_CreateFile(t *testing.T) {
45 | fileContent := `SOME TEXT`
46 | fm := NewFileManager()
47 | fm.CreateFile("test.txt", []byte(fileContent))
48 | require.DirExists(t, allureDir)
49 | defer os.RemoveAll(allureDir)
50 |
51 | files, _ := os.ReadDir(allureDir)
52 | require.Len(t, files, 1)
53 | var file *os.File
54 | defer file.Close()
55 |
56 | f := files[0]
57 | file, _ = os.Open(fmt.Sprintf("%s/%s", allureDir, f.Name()))
58 | bytes, readErr := io.ReadAll(file)
59 | require.NoError(t, readErr)
60 | require.Equal(t, fileContent, string(bytes))
61 | }
62 |
--------------------------------------------------------------------------------
/pkg/allure/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/ozontech/allure-go/pkg/allure
2 |
3 | go 1.17
4 |
5 | require (
6 | github.com/google/uuid v1.3.0
7 | github.com/pkg/errors v0.9.1
8 | github.com/stretchr/testify v1.7.1
9 | )
10 |
11 | require (
12 | github.com/davecgh/go-spew v1.1.1 // indirect
13 | github.com/pmezard/go-difflib v1.0.0 // indirect
14 | gopkg.in/yaml.v3 v3.0.0 // indirect
15 | )
16 |
--------------------------------------------------------------------------------
/pkg/allure/go.sum:
--------------------------------------------------------------------------------
1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
5 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
6 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
7 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
8 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
9 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
10 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
11 | github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
12 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
13 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
14 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
15 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
16 | gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
17 | gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
18 |
--------------------------------------------------------------------------------
/pkg/allure/link.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "strings"
7 | )
8 |
9 | // Link is an implementation of the Link entity used by Allure to specify the links needed for test reports.
10 | // Such as:
11 | // - A link to a task in Issue tracker.
12 | // - A link to a test case in the TMS
13 | // - Any other link (e.g. a link to an environment pod)
14 | type Link struct {
15 | Name string `json:"name"` // Link name
16 | Type string `json:"type"` // Link's Type (issue, test case or any other)
17 | URL string `json:"url"` // Link URL
18 | }
19 |
20 | // LinkTypes ...
21 | type LinkTypes string
22 |
23 | // LinkTypes constants
24 | const (
25 | LINK LinkTypes = "link"
26 | ISSUE LinkTypes = "issue"
27 | TESTCASE LinkTypes = "test_case"
28 | TMS LinkTypes = "tms"
29 | )
30 |
31 | // NewLink Constructor. Builds and returns a new `allure.Link` object.
32 | func NewLink(name string, linkType LinkTypes, url string) *Link {
33 | return &Link{name, string(linkType), url}
34 | }
35 |
36 | // TestCaseLink returns TESTCASE type link
37 | func TestCaseLink(testCase string) *Link {
38 | linkName := fmt.Sprintf("TestCase[%s]", testCase)
39 | return NewLink(linkName, TESTCASE, fmt.Sprintf(getTestCasePattern(), testCase))
40 | }
41 |
42 | // IssueLink returns ISSUE type link
43 | func IssueLink(issue string) *Link {
44 | linkName := fmt.Sprintf("Issue[%s]", issue)
45 | return NewLink(linkName, ISSUE, fmt.Sprintf(getIssuePattern(), issue))
46 | }
47 |
48 | // LinkLink returns LINK type link
49 | func LinkLink(linkname, link string) *Link {
50 | return NewLink(linkname, LINK, link)
51 | }
52 |
53 | // TmsLink returns TMS type link
54 | func TmsLink(testCase string) *Link {
55 | return NewLink(testCase, TMS, fmt.Sprintf(getTmsPattern(), testCase))
56 | }
57 |
58 | // TmsLinks returns multiple TmsLink type link
59 | func TmsLinks(testCases ...string) []*Link {
60 | result := make([]*Link, 0, len(testCases))
61 |
62 | for _, testCase := range testCases {
63 | url := fmt.Sprintf(getTmsPattern(), testCase)
64 |
65 | result = append(result, NewLink(testCase, TMS, url))
66 | }
67 |
68 | return result
69 | }
70 |
71 | func getIssuePattern() string {
72 | return getPattern(issuePatternEnvKey, "%s")
73 | }
74 |
75 | func getTestCasePattern() string {
76 | return getPattern(testCasePatternEnvKey, "%s")
77 | }
78 |
79 | func getTmsPattern() string {
80 | return getPattern(tmsLinkPatternEnvKey, "%s")
81 | }
82 |
83 | func getPattern(envKey string, defaultPattern string) string {
84 | pattern := os.Getenv(envKey)
85 |
86 | if !strings.Contains(pattern, "%s") {
87 | fmt.Printf("Provided pattern (%s) is either missing '%%s' or empty.\n", pattern)
88 | fmt.Printf("Use %s environment variable to supply correct one.\n", envKey)
89 | fmt.Printf("Default pattern will be used (%s).\n", defaultPattern)
90 |
91 | return defaultPattern
92 | }
93 |
94 | return pattern
95 | }
96 |
--------------------------------------------------------------------------------
/pkg/allure/link_test.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "os"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/require"
8 | )
9 |
10 | func TestLinkTypes(t *testing.T) {
11 | link := "link"
12 | issue := "issue"
13 | testCase := "test_case"
14 | tms := "tms"
15 |
16 | require.Equal(t, link, string(LINK))
17 | require.Equal(t, issue, string(ISSUE))
18 | require.Equal(t, testCase, string(TESTCASE))
19 | require.Equal(t, tms, string(TMS))
20 | }
21 |
22 | func TestNewLink(t *testing.T) {
23 | link := NewLink("testLink", LINK, "https://www.testLink.com")
24 | issue := NewLink("issueLink", ISSUE, "https://www.testIssue.com")
25 | testCase := NewLink("testCaseLink", TESTCASE, "https://www.testCase.com")
26 | tms := NewLink("tmsLink", TMS, "https://www.tmslink.com")
27 |
28 | require.NotNil(t, link)
29 | require.Equal(t, "testLink", link.Name)
30 | require.Equal(t, string(LINK), link.Type)
31 | require.Equal(t, "https://www.testLink.com", link.URL)
32 |
33 | require.NotNil(t, issue)
34 | require.Equal(t, "issueLink", issue.Name)
35 | require.Equal(t, string(ISSUE), issue.Type)
36 | require.Equal(t, "https://www.testIssue.com", issue.URL)
37 |
38 | require.NotNil(t, testCase)
39 | require.Equal(t, "testCaseLink", testCase.Name)
40 | require.Equal(t, string(TESTCASE), testCase.Type)
41 | require.Equal(t, "https://www.testCase.com", testCase.URL)
42 |
43 | require.NotNil(t, tms)
44 | require.Equal(t, "tmsLink", tms.Name)
45 | require.Equal(t, string(TMS), tms.Type)
46 | require.Equal(t, "https://www.tmslink.com", tms.URL)
47 | }
48 |
49 | func TestTestCaseLink_noEnv(t *testing.T) {
50 | testCase := TestCaseLink("TEST-112")
51 | require.NotNil(t, testCase)
52 | require.Equal(t, "TestCase[TEST-112]", testCase.Name)
53 | require.Equal(t, string(TESTCASE), testCase.Type)
54 | require.Equal(t, "TEST-112", testCase.URL)
55 | }
56 |
57 | func TestTestCaseLink_Env(t *testing.T) {
58 | os.Setenv(testCasePatternEnvKey, "https://jira-mock.com/%s")
59 | defer os.Setenv(testCasePatternEnvKey, "")
60 | testCase := TestCaseLink("TEST-112")
61 | require.NotNil(t, testCase)
62 | require.Equal(t, "TestCase[TEST-112]", testCase.Name)
63 | require.Equal(t, string(TESTCASE), testCase.Type)
64 | require.Equal(t, "https://jira-mock.com/TEST-112", testCase.URL)
65 | }
66 |
67 | func TestIssueLink_noEnv(t *testing.T) {
68 | testCase := IssueLink("TEST-112")
69 | require.NotNil(t, testCase)
70 | require.Equal(t, "Issue[TEST-112]", testCase.Name)
71 | require.Equal(t, string(ISSUE), testCase.Type)
72 | require.Equal(t, "TEST-112", testCase.URL)
73 | }
74 |
75 | func TestIssueLink_Env(t *testing.T) {
76 | os.Setenv(issuePatternEnvKey, "https://jira-mock.com/%s")
77 | defer os.Setenv(issuePatternEnvKey, "")
78 | testCase := IssueLink("TEST-112")
79 | require.NotNil(t, testCase)
80 | require.Equal(t, "Issue[TEST-112]", testCase.Name)
81 | require.Equal(t, string(ISSUE), testCase.Type)
82 | require.Equal(t, "https://jira-mock.com/TEST-112", testCase.URL)
83 | }
84 |
85 | func TestTmsLink_noEnv(t *testing.T) {
86 | testCase := TmsLink("TMS-112")
87 | require.NotNil(t, testCase)
88 | require.Equal(t, "TMS-112", testCase.Name)
89 | require.Equal(t, string(TMS), testCase.Type)
90 | require.Equal(t, "TMS-112", testCase.URL)
91 | }
92 |
93 | func TestTmsLink_Env(t *testing.T) {
94 | os.Setenv(tmsLinkPatternEnvKey, "https://tms-mock.com/%s")
95 | defer os.Setenv(tmsLinkPatternEnvKey, "")
96 | testCase := TmsLink("TMS-112")
97 | require.NotNil(t, testCase)
98 | require.Equal(t, "TMS-112", testCase.Name)
99 | require.Equal(t, string(TMS), testCase.Type)
100 | require.Equal(t, "https://tms-mock.com/TMS-112", testCase.URL)
101 | }
102 |
103 | func TestTmsLinks_noEnv(t *testing.T) {
104 | testCase := TmsLinks("TMS-110", "TMS-112")
105 | require.NotNil(t, testCase)
106 | require.Len(t, testCase, 2)
107 | require.Equal(t, "TMS-110", testCase[0].Name)
108 | require.Equal(t, "TMS-112", testCase[1].Name)
109 | require.Equal(t, string(TMS), testCase[0].Type)
110 | require.Equal(t, string(TMS), testCase[1].Type)
111 | require.Equal(t, "TMS-110", testCase[0].URL)
112 | require.Equal(t, "TMS-112", testCase[1].URL)
113 | }
114 |
115 | func TestTmsLinks_Env(t *testing.T) {
116 | os.Setenv(tmsLinkPatternEnvKey, "https://tms-mock.com/%s")
117 | defer os.Setenv(tmsLinkPatternEnvKey, "")
118 | testCase := TmsLinks("TEST-110", "TEST-112")
119 | require.NotNil(t, testCase)
120 | require.Len(t, testCase, 2)
121 | require.Equal(t, "TEST-110", testCase[0].Name)
122 | require.Equal(t, "TEST-112", testCase[1].Name)
123 | require.Equal(t, string(TMS), testCase[0].Type)
124 | require.Equal(t, string(TMS), testCase[1].Type)
125 | require.Equal(t, "https://tms-mock.com/TEST-110", testCase[0].URL)
126 | require.Equal(t, "https://tms-mock.com/TEST-112", testCase[1].URL)
127 | }
128 |
--------------------------------------------------------------------------------
/pkg/allure/parameter_test.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "encoding/json"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/require"
8 | )
9 |
10 | func TestNewParameter(t *testing.T) {
11 | const paramName = "paramName"
12 | paramValue := "paramValue"
13 | param := NewParameter(paramName, paramValue)
14 | require.NotNil(t, param)
15 | require.Equal(t, paramName, param.Name)
16 | require.Equal(t, string(paramValue), param.GetValue())
17 | }
18 |
19 | func TestNewParameters_even(t *testing.T) {
20 | params := NewParameters("p1", "v1", "p2", "v2", "p3", "v3")
21 | require.NotNil(t, params)
22 | require.Len(t, params, 3)
23 |
24 | require.Equal(t, "p1", params[0].Name)
25 | require.Equal(t, "v1", params[0].GetValue())
26 | require.Equal(t, "p2", params[1].Name)
27 | require.Equal(t, "v2", params[1].GetValue())
28 | require.Equal(t, "p3", params[2].Name)
29 | require.Equal(t, "v3", params[2].GetValue())
30 | }
31 |
32 | func TestNewParameters_odd(t *testing.T) {
33 | params := NewParameters("p1", "v1", "p2", "v2", "p3", 24)
34 | require.NotNil(t, params)
35 | require.Len(t, params, 3)
36 |
37 | require.Equal(t, "p1", params[0].Name)
38 | require.Equal(t, "v1", params[0].GetValue())
39 |
40 | require.Equal(t, "p2", params[1].Name)
41 | require.Equal(t, "v2", params[1].GetValue())
42 |
43 | require.Equal(t, "p3", params[2].Name)
44 | require.Equal(t, "24", params[2].GetValue())
45 | }
46 |
47 | func TestParameterUnmarshal(t *testing.T) {
48 | t.Run("string", func(t *testing.T) {
49 | const data = `{"name": "epic", "value": "\"very epic indeed\""}`
50 |
51 | var param Parameter
52 |
53 | require.NoError(t, json.Unmarshal([]byte(data), ¶m))
54 |
55 | require.Equal(t, Parameter{
56 | Name: "epic",
57 | Value: "\"very epic indeed\"",
58 | }, param)
59 |
60 | require.Equal(t, "very epic indeed", param.GetValue())
61 | })
62 |
63 | t.Run("int", func(t *testing.T) {
64 | const data = `{"name": "epic", "value": 83294782375982}`
65 |
66 | var param Parameter
67 |
68 | require.NoError(t, json.Unmarshal([]byte(data), ¶m))
69 |
70 | require.Equal(t, Parameter{
71 | Name: "epic",
72 | Value: int64(83294782375982),
73 | }, param)
74 |
75 | require.Equal(t, "83294782375982", param.GetValue())
76 | })
77 |
78 | t.Run("float", func(t *testing.T) {
79 | const data = `{"name": "epic", "value": 3.14159}`
80 |
81 | var param Parameter
82 |
83 | require.NoError(t, json.Unmarshal([]byte(data), ¶m))
84 |
85 | require.Equal(t, Parameter{
86 | Name: "epic",
87 | Value: 3.14159,
88 | }, param)
89 |
90 | require.Equal(t, "3.14159", param.GetValue())
91 | })
92 |
93 | t.Run("slice", func(t *testing.T) {
94 | const data = `{"name": "epic", "value": [1, 2, 3]}`
95 |
96 | var param Parameter
97 |
98 | require.NoError(t, json.Unmarshal([]byte(data), ¶m))
99 |
100 | require.Equal(t, Parameter{
101 | Name: "epic",
102 | Value: []interface{}{int64(1), int64(2), int64(3)},
103 | }, param)
104 |
105 | require.Equal(t, "[1 2 3]", param.GetValue())
106 | })
107 |
108 | t.Run("map", func(t *testing.T) {
109 | const data = `{"name": "epic", "value": {"a": [1, true, 3.14]}}`
110 |
111 | var param Parameter
112 |
113 | require.NoError(t, json.Unmarshal([]byte(data), ¶m))
114 |
115 | require.Equal(t, Parameter{
116 | Name: "epic",
117 | Value: map[string]interface{}{
118 | "a": []interface{}{int64(1), true, 3.14},
119 | },
120 | }, param)
121 |
122 | require.Equal(t, "map[a:[1 true 3.14]]", param.GetValue())
123 | })
124 | }
125 |
--------------------------------------------------------------------------------
/pkg/allure/status.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | // Status is Step's Status info
4 | type Status string
5 |
6 | // Status constants
7 | const (
8 | Passed Status = "passed"
9 | Failed Status = "failed"
10 | Skipped Status = "skipped"
11 | Broken Status = "broken"
12 | Unknown Status = "unknown"
13 | )
14 |
15 | func (s Status) String() string {
16 | return string(s)
17 | }
18 |
--------------------------------------------------------------------------------
/pkg/allure/status_detail.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | // StatusDetail ...
4 | type StatusDetail struct {
5 | Message string `json:"message"` // Abridged version of the message
6 | Trace string `json:"trace"` // Full message
7 | }
8 |
--------------------------------------------------------------------------------
/pkg/allure/status_test.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/require"
7 | )
8 |
9 | func TestStatus(t *testing.T) {
10 | require.Equal(t, "passed", string(Passed))
11 | require.Equal(t, "failed", string(Failed))
12 | require.Equal(t, "skipped", string(Skipped))
13 | require.Equal(t, "broken", string(Broken))
14 | require.Equal(t, "unknown", string(Unknown))
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/allure/time.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import "time"
4 |
5 | // GetNow returns [time.Now] as UNIX milliseconds
6 | func GetNow() int64 {
7 | return time.Now().UnixMilli()
8 | }
9 |
--------------------------------------------------------------------------------
/pkg/allure/time_test.go:
--------------------------------------------------------------------------------
1 | package allure
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/require"
7 | )
8 |
9 | func TestGetNow(t *testing.T) {
10 | require.NotZero(t, GetNow())
11 | }
12 |
--------------------------------------------------------------------------------
/pkg/framework/.golangci.yaml:
--------------------------------------------------------------------------------
1 | # More info on config here: https://github.com/golangci/golangci-lint#config-file
2 | run:
3 | deadline: 10s
4 | timeout: 5m
5 | issues-exit-code: 1
6 | tests: true
7 | skip-dirs:
8 | - bin
9 | - vendor
10 | - var
11 | - tmp
12 | skip-files:
13 | - \.pb\.go$
14 | - \.pb\.goclay\.go$
15 | - \_test.go$
16 |
17 | output:
18 | format: colored-line-number
19 | print-issued-lines: true
20 | print-linter-name: true
21 |
22 | linters-settings:
23 | govet:
24 | check-shadowing: true
25 | golint:
26 | min-confidence: 0
27 | dupl:
28 | threshold: 100
29 | goconst:
30 | min-len: 2
31 | min-occurrences: 2
32 |
33 | linters:
34 | disable-all: true
35 | enable:
36 | - golint
37 | - govet
38 | - errcheck
39 | - deadcode
40 | - structcheck
41 | - varcheck
42 | - ineffassign
43 | - typecheck
44 | - dupl
45 | - goconst
46 | - gosec
47 | - goimports
48 | - megacheck
49 |
50 |
51 | issues:
52 | exclude-use-default: false
53 | exclude:
54 | # _ instead of err checks
55 | - G103
56 | - G104
57 | - G306
58 | # md5 using for hash generation, not for security, so ignore this
59 | - G401
60 | - G501
61 | # for "public interface + private struct implementation" cases only!
62 | - exported func * returns unexported type *, which can be annoying to use
63 | # can be removed in the development phase
64 | # - (comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)
65 | # not for the active development - can be removed in the stable phase
66 | - should have a package comment, unless it's in another file for this package
67 | - don't use an underscore in package name
68 | # errcheck: Almost all programs ignore errors on these functions and in most cases it's ok
69 | - Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv|.*Rollback). is not checked
70 | - should check returned error before deferring
71 | - should have comment or be unexported
72 | - a blank import should be only in a main or test package
73 | - Can't process result by diff processor
74 |
--------------------------------------------------------------------------------
/pkg/framework/Makefile:
--------------------------------------------------------------------------------
1 | APP?=allure-testify
2 | RELEASE?=0.5.0
3 | GOOS?=darwin
4 |
5 | COMMIT?=$(shell git rev-parse --short HEAD)
6 | BUILD_TIME?=$(shell date -u '+%Y-%m-%d_%H:%M:%S')
7 |
8 | export GO111MODULE=on
9 | export GOSUMDB=off
10 | LOCAL_BIN:=$(CURDIR)/bin
11 |
12 | ##################### GOLANG-CI RELATED CHECKS #####################
13 | # Check global GOLANGCI-LINT
14 | GOLANGCI_BIN:=$(LOCAL_BIN)/golangci-lint
15 | GOLANGCI_TAG:=1.38.0
16 |
17 | # Check local bin version
18 | ifneq ($(wildcard $(GOLANGCI_BIN)),)
19 | GOLANGCI_BIN_VERSION:=$(shell $(GOLANGCI_BIN) --version)
20 | ifneq ($(GOLANGCI_BIN_VERSION),)
21 | GOLANGCI_BIN_VERSION_SHORT:=$(shell echo "$(GOLANGCI_BIN_VERSION)" | sed -E 's/.* version (.*) built from .* on .*/\1/g')
22 | else
23 | GOLANGCI_BIN_VERSION_SHORT:=0
24 | endif
25 | ifneq "$(GOLANGCI_TAG)" "$(word 1, $(sort $(GOLANGCI_TAG) $(GOLANGCI_BIN_VERSION_SHORT)))"
26 | GOLANGCI_BIN:=
27 | endif
28 | endif
29 |
30 | # Check global bin version
31 | ifneq (, $(shell which golangci-lint))
32 | GOLANGCI_VERSION:=$(shell golangci-lint --version 2> /dev/null )
33 | ifneq ($(GOLANGCI_VERSION),)
34 | GOLANGCI_VERSION_SHORT:=$(shell echo "$(GOLANGCI_VERSION)"|sed -E 's/.* version (.*) built from .* on .*/\1/g')
35 | else
36 | GOLANGCI_VERSION_SHORT:=0
37 | endif
38 | ifeq "$(GOLANGCI_TAG)" "$(word 1, $(sort $(GOLANGCI_TAG) $(GOLANGCI_VERSION_SHORT)))"
39 | GOLANGCI_BIN:=$(shell which golangci-lint)
40 | endif
41 | endif
42 | ##################### GOLANG-CI RELATED CHECKS #####################
43 |
44 | # run full lint like in pipeline
45 | .PHONY: lint
46 | lint: install-lint
47 | $(GOLANGCI_BIN) run --config=.golangci.yaml ./...
48 |
49 |
50 | .PHONY: install-lint
51 | install-lint:
52 | ifeq ($(wildcard $(GOLANGCI_BIN)),)
53 | $(info #Downloading golangci-lint v$(GOLANGCI_TAG))
54 | tmp=$$(mktemp -d) && cd $$tmp && pwd && go mod init temp && go get -d github.com/golangci/golangci-lint/cmd/golangci-lint@v$(GOLANGCI_TAG) && \
55 | go build -ldflags "-X 'main.version=$(GOLANGCI_TAG)' -X 'main.commit=test' -X 'main.date=test'" -o $(LOCAL_BIN)/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint && \
56 | rm -rf $$tmp
57 | GOLANGCI_BIN:=$(LOCAL_BIN)/golangci-lint
58 | endif
59 |
60 | .PHONY: test
61 | test:
62 | go test ./... -cover
--------------------------------------------------------------------------------
/pkg/framework/asserts_wrapper/helper/asserts_helper.go:
--------------------------------------------------------------------------------
1 | package helper
2 |
3 | import "github.com/ozontech/allure-go/pkg/framework/asserts_wrapper/wrapper"
4 |
5 | // NewAssertsHelper inits new Assert interface
6 | func NewAssertsHelper(t ProviderT) AssertsHelper {
7 | return &a{
8 | t: t,
9 | asserts: wrapper.NewAsserts(t),
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/pkg/framework/asserts_wrapper/helper/asserts_helper_test.go:
--------------------------------------------------------------------------------
1 | package helper
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/require"
7 |
8 | "github.com/ozontech/allure-go/pkg/allure"
9 | )
10 |
11 | type tAssertMock struct {
12 | }
13 |
14 | func (p *tAssertMock) Step(step *allure.Step) {
15 | }
16 |
17 | func (p *tAssertMock) Errorf(format string, msgAndArgs ...interface{}) {
18 | }
19 |
20 | func (p *tAssertMock) FailNow() {
21 | }
22 |
23 | func TestNewAssertsHelper(t *testing.T) {
24 | h := NewAssertsHelper(&tAssertMock{})
25 | require.NotNil(t, h)
26 | }
27 |
--------------------------------------------------------------------------------
/pkg/framework/asserts_wrapper/helper/interfaces.go:
--------------------------------------------------------------------------------
1 | package helper
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/ozontech/allure-go/pkg/allure"
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | type ProviderT interface {
11 | Step(step *allure.Step)
12 | Errorf(format string, args ...interface{})
13 | FailNow()
14 | }
15 |
16 | // AssertsHelper ...
17 | type AssertsHelper interface {
18 | Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{})
19 | Same(expected interface{}, actual interface{}, msgAndArgs ...interface{})
20 | NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{})
21 | Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{})
22 | NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{})
23 | EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{})
24 | NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{})
25 | Error(err error, msgAndArgs ...interface{})
26 | NoError(err error, msgAndArgs ...interface{})
27 | EqualError(theError error, errString string, msgAndArgs ...interface{})
28 | ErrorIs(err error, target error, msgAndArgs ...interface{})
29 | ErrorAs(err error, target interface{}, msgAndArgs ...interface{})
30 | NotNil(object interface{}, msgAndArgs ...interface{})
31 | Nil(object interface{}, msgAndArgs ...interface{})
32 | Len(object interface{}, length int, msgAndArgs ...interface{})
33 | NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{})
34 | Contains(s interface{}, contains interface{}, msgAndArgs ...interface{})
35 | Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
36 | GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
37 | Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
38 | LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
39 | Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{})
40 | Empty(object interface{}, msgAndArgs ...interface{})
41 | NotEmpty(object interface{}, msgAndArgs ...interface{})
42 | WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{})
43 | JSONEq(expected, actual string, msgAndArgs ...interface{})
44 | JSONContains(expected, actual string, msgAndArgs ...interface{})
45 | Subset(list, subset interface{}, msgAndArgs ...interface{})
46 | NotSubset(list, subset interface{}, msgAndArgs ...interface{})
47 | IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{})
48 | True(value bool, msgAndArgs ...interface{})
49 | False(value bool, msgAndArgs ...interface{})
50 | Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{})
51 | ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{})
52 | DirExists(path string, msgAndArgs ...interface{})
53 | Condition(condition assert.Comparison, msgAndArgs ...interface{})
54 | Zero(i interface{}, msgAndArgs ...interface{})
55 | NotZero(i interface{}, msgAndArgs ...interface{})
56 | InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{})
57 | Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{})
58 | }
59 |
--------------------------------------------------------------------------------
/pkg/framework/asserts_wrapper/helper/require_helper.go:
--------------------------------------------------------------------------------
1 | package helper
2 |
3 | import (
4 | "github.com/ozontech/allure-go/pkg/framework/asserts_wrapper/wrapper"
5 | )
6 |
7 | // NewRequireHelper inits new Require interface
8 | func NewRequireHelper(t ProviderT) AssertsHelper {
9 | return &a{
10 | t: t,
11 | asserts: wrapper.NewRequire(t),
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/pkg/framework/asserts_wrapper/helper/require_helper_test.go:
--------------------------------------------------------------------------------
1 | package helper
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/require"
7 |
8 | "github.com/ozontech/allure-go/pkg/allure"
9 | )
10 |
11 | type tRequireMock struct {
12 | }
13 |
14 | func (p *tRequireMock) Step(step *allure.Step) {
15 | }
16 |
17 | func (p *tRequireMock) Errorf(format string, msgAndArgs ...interface{}) {
18 | }
19 |
20 | func (p *tRequireMock) FailNow() {
21 | }
22 |
23 | func TestNewRequireHelper(t *testing.T) {
24 | h := NewAssertsHelper(&tRequireMock{})
25 | require.NotNil(t, h)
26 | }
27 |
--------------------------------------------------------------------------------
/pkg/framework/asserts_wrapper/wrapper/helper.go:
--------------------------------------------------------------------------------
1 | package wrapper
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/ozontech/allure-go/pkg/allure"
7 | )
8 |
9 | type Provider interface {
10 | Step(step *allure.Step)
11 | }
12 |
13 | type assertHelper struct {
14 | prefix string
15 | }
16 |
17 | func (h *assertHelper) getStepName(assertName string, msgAndArgs ...interface{}) string {
18 | if len(msgAndArgs) == 0 {
19 | return fmt.Sprintf("%s: %s", h.prefix, assertName)
20 | }
21 | return fmt.Sprintf("%s: %s", h.prefix, messageFromMsgAndArgs(msgAndArgs...))
22 | }
23 |
24 | func (h *assertHelper) WithNewStep(t TestingT, provider Provider, assertName string, assert func(t TestingT) bool, params []*allure.Parameter, msgAndArgs ...interface{}) bool {
25 | var (
26 | step = allure.NewSimpleStep(h.getStepName(assertName, msgAndArgs...), params...)
27 | result = assert(t)
28 | )
29 |
30 | provider.Step(step)
31 | if !result {
32 | step.Failed()
33 | }
34 |
35 | return result
36 | }
37 |
38 | func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
39 | if len(msgAndArgs) == 0 || msgAndArgs == nil {
40 | return ""
41 | }
42 | if len(msgAndArgs) == 1 {
43 | msg := msgAndArgs[0]
44 | if msgAsStr, ok := msg.(string); ok {
45 | return msgAsStr
46 | }
47 | return fmt.Sprintf("%+v", msg)
48 | }
49 | if len(msgAndArgs) > 1 {
50 | return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
51 | }
52 | return ""
53 | }
54 |
--------------------------------------------------------------------------------
/pkg/framework/asserts_wrapper/wrapper/helper_test.go:
--------------------------------------------------------------------------------
1 | package wrapper
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/require"
7 |
8 | "github.com/ozontech/allure-go/pkg/allure"
9 | )
10 |
11 | type tMock struct {
12 | steps []*allure.Step
13 | errorF bool
14 | errorFString string
15 | failNow bool
16 | }
17 |
18 | func newTMock() *tMock {
19 | return &tMock{steps: make([]*allure.Step, 0)}
20 | }
21 |
22 | func (p *tMock) Step(step *allure.Step) {
23 | p.steps = append(p.steps, step)
24 | }
25 |
26 | func (p *tMock) Errorf(format string, msgAndArgs ...interface{}) {
27 | p.errorFString = format
28 | p.errorF = true
29 | }
30 |
31 | func (p *tMock) FailNow() {
32 | p.failNow = true
33 | }
34 |
35 | func TestAssertHelper_getStepName(t *testing.T) {
36 | a := &assertHelper{prefix: "ASSERT"}
37 | require.Equal(t, "ASSERT: Test", a.getStepName("Test"))
38 |
39 | b := &assertHelper{prefix: "REQUIRE"}
40 | require.Equal(t, "REQUIRE: Test", b.getStepName("Test"))
41 | }
42 |
43 | func TestAssertHelper_withNewStep_requireFalse(t *testing.T) {
44 | a := &assertHelper{prefix: "ASSERT"}
45 | mock := newTMock()
46 | param := allure.NewParameters("pName", "pValue")
47 | result := a.WithNewStep(mock, mock, "Test", func(t TestingT) bool { return true }, param)
48 | require.True(t, result)
49 | require.NotEmpty(t, mock.steps)
50 | require.Len(t, mock.steps, 1)
51 | require.Equal(t, "ASSERT: Test", mock.steps[0].Name)
52 | require.Equal(t, allure.Passed, mock.steps[0].Status)
53 | require.NotEmpty(t, mock.steps[0].Parameters)
54 | require.Len(t, mock.steps[0].Parameters, 1)
55 | require.Equal(t, param[0].Name, mock.steps[0].Parameters[0].Name)
56 | require.Equal(t, param[0].GetValue(), mock.steps[0].Parameters[0].GetValue())
57 |
58 | mock2 := newTMock()
59 | param2 := allure.NewParameter("pName", "pValue")
60 | result2 := a.WithNewStep(mock2, mock2, "Test", func(t TestingT) bool { return false }, param)
61 | require.False(t, result2)
62 | require.NotEmpty(t, mock2.steps)
63 | require.Len(t, mock2.steps, 1)
64 | require.Equal(t, "ASSERT: Test", mock2.steps[0].Name)
65 | require.Equal(t, allure.Failed, mock2.steps[0].Status)
66 | require.NotEmpty(t, mock2.steps[0].Parameters)
67 | require.Len(t, mock2.steps[0].Parameters, 1)
68 | require.Equal(t, param2.Name, mock2.steps[0].Parameters[0].Name)
69 | require.Equal(t, param2.GetValue(), mock2.steps[0].Parameters[0].GetValue())
70 | }
71 |
72 | func TestAssertHelper_withNewStep_requireTrue(t *testing.T) {
73 | a := &assertHelper{prefix: "REQUIRE"}
74 | mock := newTMock()
75 | param := allure.NewParameters("pName", "pValue")
76 | result := a.WithNewStep(mock, mock, "Test", func(t TestingT) bool { return true }, param)
77 | require.True(t, result)
78 | require.NotEmpty(t, mock.steps)
79 | require.Len(t, mock.steps, 1)
80 | require.Equal(t, "REQUIRE: Test", mock.steps[0].Name)
81 | require.Equal(t, allure.Passed, mock.steps[0].Status)
82 | require.NotEmpty(t, mock.steps[0].Parameters)
83 | require.Len(t, mock.steps[0].Parameters, 1)
84 | require.Equal(t, param[0].Name, mock.steps[0].Parameters[0].Name)
85 | require.Equal(t, param[0].GetValue(), mock.steps[0].Parameters[0].GetValue())
86 |
87 | mock2 := newTMock()
88 | param2 := allure.NewParameter("pName", "pValue")
89 | result2 := a.WithNewStep(mock2, mock2, "Test", func(t TestingT) bool { return false }, param)
90 | require.False(t, result2)
91 | require.NotEmpty(t, mock2.steps)
92 | require.Len(t, mock2.steps, 1)
93 | require.Equal(t, "REQUIRE: Test", mock2.steps[0].Name)
94 | require.Equal(t, allure.Failed, mock2.steps[0].Status)
95 | require.NotEmpty(t, mock2.steps[0].Parameters)
96 | require.Len(t, mock2.steps[0].Parameters, 1)
97 | require.Equal(t, param2.Name, mock2.steps[0].Parameters[0].Name)
98 | require.Equal(t, param2.GetValue(), mock2.steps[0].Parameters[0].GetValue())
99 | }
100 |
--------------------------------------------------------------------------------
/pkg/framework/asserts_wrapper/wrapper/interfaces.go:
--------------------------------------------------------------------------------
1 | package wrapper
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | // AssertsWrapper ...
10 | type AssertsWrapper interface {
11 | Exactly(provider Provider, expected interface{}, actual interface{}, msgAndArgs ...interface{})
12 | Same(provider Provider, expected interface{}, actual interface{}, msgAndArgs ...interface{})
13 | NotSame(provider Provider, expected interface{}, actual interface{}, msgAndArgs ...interface{})
14 | Equal(provider Provider, expected interface{}, actual interface{}, msgAndArgs ...interface{})
15 | NotEqual(provider Provider, expected interface{}, actual interface{}, msgAndArgs ...interface{})
16 | EqualValues(provider Provider, expected interface{}, actual interface{}, msgAndArgs ...interface{})
17 | NotEqualValues(provider Provider, expected interface{}, actual interface{}, msgAndArgs ...interface{})
18 | Error(provider Provider, err error, msgAndArgs ...interface{})
19 | NoError(provider Provider, err error, msgAndArgs ...interface{})
20 | EqualError(provider Provider, theError error, errString string, msgAndArgs ...interface{})
21 | ErrorIs(provider Provider, err error, target error, msgAndArgs ...interface{})
22 | ErrorAs(provider Provider, err error, target interface{}, msgAndArgs ...interface{})
23 | NotNil(provider Provider, object interface{}, msgAndArgs ...interface{})
24 | Nil(provider Provider, object interface{}, msgAndArgs ...interface{})
25 | Len(provider Provider, object interface{}, length int, msgAndArgs ...interface{})
26 | NotContains(provider Provider, s interface{}, contains interface{}, msgAndArgs ...interface{})
27 | Contains(provider Provider, s interface{}, contains interface{}, msgAndArgs ...interface{})
28 | Greater(provider Provider, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
29 | GreaterOrEqual(provider Provider, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
30 | Less(provider Provider, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
31 | LessOrEqual(provider Provider, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
32 | Implements(provider Provider, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{})
33 | Empty(provider Provider, object interface{}, msgAndArgs ...interface{})
34 | NotEmpty(provider Provider, object interface{}, msgAndArgs ...interface{})
35 | WithinDuration(provider Provider, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{})
36 | JSONEq(provider Provider, expected, actual string, msgAndArgs ...interface{})
37 | JSONContains(provider Provider, expected, actual string, msgAndArgs ...interface{})
38 | Subset(provider Provider, list, subset interface{}, msgAndArgs ...interface{})
39 | NotSubset(provider Provider, list, subset interface{}, msgAndArgs ...interface{})
40 | IsType(provider Provider, expectedType interface{}, object interface{}, msgAndArgs ...interface{})
41 | True(provider Provider, value bool, msgAndArgs ...interface{})
42 | False(provider Provider, value bool, msgAndArgs ...interface{})
43 | Regexp(provider Provider, rx interface{}, str interface{}, msgAndArgs ...interface{})
44 | ElementsMatch(provider Provider, listA interface{}, listB interface{}, msgAndArgs ...interface{})
45 | DirExists(provider Provider, path string, msgAndArgs ...interface{})
46 | Condition(provider Provider, condition assert.Comparison, msgAndArgs ...interface{})
47 | Zero(provider Provider, i interface{}, msgAndArgs ...interface{})
48 | NotZero(provider Provider, i interface{}, msgAndArgs ...interface{})
49 | InDelta(provider Provider, expected, actual interface{}, delta float64, msgAndArgs ...interface{})
50 | Eventually(provider Provider, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{})
51 | }
52 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/adapter/suite_adapter.go:
--------------------------------------------------------------------------------
1 | package adapter
2 |
3 | import (
4 | "github.com/ozontech/allure-go/pkg/allure"
5 | "github.com/ozontech/allure-go/pkg/framework/provider"
6 | )
7 |
8 | // SuiteAdapter describes behavior of the suite
9 | // such as before/after all functions, package name, runner name, suite path and suite name
10 | type SuiteAdapter struct {
11 | packageName string
12 | runner string
13 | fullSuiteName string
14 | suiteName string
15 | parentSuite string
16 |
17 | beforeAll func(provider.T)
18 | afterAll func(provider.T)
19 |
20 | container *allure.Container
21 | }
22 |
23 | // NewSuiteMeta returns SuiteAdapter pointer
24 | func NewSuiteMeta(packageName, runner, fullSuiteName, suiteName string) *SuiteAdapter {
25 | return &SuiteAdapter{
26 | packageName: packageName,
27 | runner: runner,
28 | fullSuiteName: fullSuiteName,
29 | suiteName: suiteName,
30 | container: allure.NewContainer(),
31 | }
32 | }
33 |
34 | func NewSuiteMetaWithParent(packageName, runner, fullSuiteName, suiteName, parentSuite string) *SuiteAdapter {
35 | return &SuiteAdapter{
36 | packageName: packageName,
37 | runner: runner,
38 | fullSuiteName: fullSuiteName,
39 | suiteName: suiteName,
40 | parentSuite: parentSuite,
41 | container: allure.NewContainer(),
42 | }
43 | }
44 |
45 | // GetPackageName returns package name
46 | func (ctx *SuiteAdapter) GetPackageName() string {
47 | return ctx.packageName
48 | }
49 |
50 | // GetRunner returns runner name
51 | func (ctx *SuiteAdapter) GetRunner() string {
52 | return ctx.runner
53 | }
54 |
55 | // GetSuiteName returns suite name
56 | func (ctx *SuiteAdapter) GetSuiteName() string {
57 | return ctx.suiteName
58 | }
59 |
60 | // GetParentSuite returns suite name
61 | func (ctx *SuiteAdapter) GetParentSuite() string {
62 | return ctx.parentSuite
63 | }
64 |
65 | // GetSuiteFullName returns full name
66 | func (ctx *SuiteAdapter) GetSuiteFullName() string {
67 | return ctx.fullSuiteName
68 | }
69 |
70 | // GetContainer returns container
71 | func (ctx *SuiteAdapter) GetContainer() *allure.Container {
72 | return ctx.container
73 | }
74 |
75 | // SetBeforeAll sets before all func
76 | func (ctx *SuiteAdapter) SetBeforeAll(hook func(provider.T)) {
77 | ctx.beforeAll = hook
78 | }
79 |
80 | // SetAfterAll sets after all func
81 | func (ctx *SuiteAdapter) SetAfterAll(hook func(provider.T)) {
82 | ctx.afterAll = hook
83 | }
84 |
85 | // GetBeforeAll returns before all func
86 | func (ctx *SuiteAdapter) GetBeforeAll() func(provider.T) {
87 | return ctx.beforeAll
88 | }
89 |
90 | // GetAfterAll returns after all func
91 | func (ctx *SuiteAdapter) GetAfterAll() func(provider.T) {
92 | return ctx.afterAll
93 | }
94 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/adapter/suite_adapter_test.go:
--------------------------------------------------------------------------------
1 | package adapter
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/require"
7 |
8 | "github.com/ozontech/allure-go/pkg/allure"
9 | "github.com/ozontech/allure-go/pkg/framework/provider"
10 | )
11 |
12 | func TestNewSuiteMeta(t *testing.T) {
13 | adapter := NewSuiteMeta("packageName", "runner", "fullName", "suiteName")
14 | require.NotNil(t, adapter)
15 | require.Equal(t, "packageName", adapter.GetPackageName())
16 | require.Equal(t, "suiteName", adapter.GetSuiteName())
17 | require.Equal(t, "runner", adapter.GetRunner())
18 | require.Equal(t, "fullName", adapter.GetSuiteFullName())
19 | require.NotNil(t, adapter.GetContainer())
20 | }
21 |
22 | func TestSuiteAdapter_GetPackageName(t *testing.T) {
23 | adapter := &SuiteAdapter{packageName: "packageName"}
24 | require.Equal(t, "packageName", adapter.GetPackageName())
25 | }
26 |
27 | func TestSuiteAdapter_GetSuiteName(t *testing.T) {
28 | adapter := &SuiteAdapter{suiteName: "suiteName"}
29 | require.Equal(t, "suiteName", adapter.GetSuiteName())
30 | }
31 |
32 | func TestSuiteAdapter_GetRunner(t *testing.T) {
33 | adapter := &SuiteAdapter{runner: "runner"}
34 | require.Equal(t, "runner", adapter.GetRunner())
35 | }
36 |
37 | func TestSuiteAdapter_GetSuiteFullName(t *testing.T) {
38 | adapter := &SuiteAdapter{fullSuiteName: "fullName"}
39 | require.Equal(t, "fullName", adapter.GetSuiteFullName())
40 | }
41 |
42 | func TestSuiteAdapter_GetBeforeAll(t *testing.T) {
43 | adapter := &SuiteAdapter{beforeAll: func(t provider.T) {}}
44 | require.NotNil(t, adapter.GetBeforeAll())
45 | }
46 |
47 | func TestSuiteAdapter_GetAfterAll(t *testing.T) {
48 | adapter := &SuiteAdapter{afterAll: func(t provider.T) {}}
49 | require.NotNil(t, adapter.GetAfterAll())
50 | }
51 |
52 | func TestSuiteAdapter_SetBeforeAll(t *testing.T) {
53 | adapter := &SuiteAdapter{}
54 | adapter.SetBeforeAll(func(t provider.T) {})
55 | require.NotNil(t, adapter.GetBeforeAll())
56 | }
57 |
58 | func TestSuiteAdapter_SetAfterAll(t *testing.T) {
59 | adapter := &SuiteAdapter{}
60 | adapter.SetAfterAll(func(t provider.T) {})
61 | require.NotNil(t, adapter.GetAfterAll())
62 | }
63 |
64 | func TestSuiteAdapter_GetContainer(t *testing.T) {
65 | c := allure.NewContainer()
66 | adapter := &SuiteAdapter{container: c}
67 | require.NotNil(t, adapter.GetContainer())
68 | require.Equal(t, c, adapter.GetContainer())
69 | }
70 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/adapter/test_adapter.go:
--------------------------------------------------------------------------------
1 | package adapter
2 |
3 | import (
4 | "os"
5 | "runtime"
6 | "strings"
7 |
8 | "github.com/ozontech/allure-go/pkg/allure"
9 | "github.com/ozontech/allure-go/pkg/framework/provider"
10 | )
11 |
12 | // TestAdapter describes behavior of the test
13 | // such as before/after each function, container, test result object, and container object
14 | type TestAdapter struct {
15 | beforeEach func(provider.T)
16 | afterEach func(provider.T)
17 |
18 | result *allure.Result
19 | container *allure.Container
20 | }
21 |
22 | // NewTestMeta returns pointer to instance of TestAdapter
23 | func NewTestMeta(suiteFullName, suiteName, testName, packageName string, tags ...string) *TestAdapter {
24 | // TODO: handle error
25 | host, _ := os.Hostname()
26 | fullName := suiteFullName
27 |
28 | // ex: suiteFullName=TestRunner/My_Test, testName=My Test => after split and replace: My_test == My_test
29 | // why? to avoid TestRunner/My_Test/My Test
30 | if callers := strings.Split(suiteFullName, "/"); callers[len(callers)-1] != strings.ReplaceAll(testName, " ", "_") {
31 | fullName = fullName + "/" + testName
32 | }
33 |
34 | newTags := make([]*allure.Label, 0, len(tags))
35 | for _, tag := range tags {
36 | newTags = append(newTags, allure.NewLabel(allure.Tag, tag))
37 | }
38 |
39 | result := allure.NewResult(testName, fullName).
40 | WithFrameWork(allure.DefaultVersion).
41 | WithHost(host).
42 | WithThread(fullName).
43 | WithLanguage(runtime.Version()).
44 | WithLaunchTags().
45 | WithSuite(suiteName).
46 | WithPackage(packageName).
47 | WithLabels(newTags...)
48 |
49 | container := allure.NewContainer()
50 | container.AddChild(result.UUID)
51 |
52 | return &TestAdapter{result: result, container: container}
53 | }
54 |
55 | // GetResult returns allure.Result pointer
56 | func (ctx *TestAdapter) GetResult() *allure.Result {
57 | return ctx.result
58 | }
59 |
60 | // SetResult sets allure.Result
61 | func (ctx *TestAdapter) SetResult(result *allure.Result) {
62 | ctx.result = result
63 | }
64 |
65 | // GetContainer returns allure.Container pointer
66 | func (ctx *TestAdapter) GetContainer() *allure.Container {
67 | return ctx.container
68 | }
69 |
70 | // SetBeforeEach sets before each function
71 | func (ctx *TestAdapter) SetBeforeEach(hook func(provider.T)) {
72 | ctx.beforeEach = hook
73 | }
74 |
75 | // GetBeforeEach returns before each function
76 | func (ctx *TestAdapter) GetBeforeEach() func(provider.T) {
77 | return ctx.beforeEach
78 | }
79 |
80 | // SetAfterEach sets after each function
81 | func (ctx *TestAdapter) SetAfterEach(hook func(provider.T)) {
82 | ctx.afterEach = hook
83 | }
84 |
85 | // GetAfterEach returns after each function
86 | func (ctx *TestAdapter) GetAfterEach() func(provider.T) {
87 | return ctx.afterEach
88 | }
89 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/adapter/test_adapter_test.go:
--------------------------------------------------------------------------------
1 | package adapter
2 |
3 | import (
4 | "os"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/require"
8 |
9 | "github.com/ozontech/allure-go/pkg/allure"
10 | "github.com/ozontech/allure-go/pkg/framework/provider"
11 | )
12 |
13 | func TestNewTestMeta(t *testing.T) {
14 | host, _ := os.Hostname()
15 |
16 | adapter := NewTestMeta("fullName", "suiteName", "testName", "packageName", "tag1", "tag2")
17 | require.Equal(t, "testName", adapter.GetResult().Name)
18 | require.Equal(t, "fullName/testName", adapter.GetResult().FullName)
19 |
20 | require.Len(t, adapter.GetResult().GetLabels(allure.Host), 1)
21 | require.Equal(t, adapter.GetResult().GetLabels(allure.Host)[0].GetValue(), host)
22 |
23 | require.Len(t, adapter.GetResult().GetLabels(allure.Framework), 1)
24 | require.Equal(t, adapter.GetResult().GetLabels(allure.Framework)[0].GetValue(), allure.DefaultVersion)
25 |
26 | require.Len(t, adapter.GetResult().GetLabels(allure.Thread), 1)
27 | require.Equal(t, "fullName/testName", adapter.GetResult().GetLabels(allure.Thread)[0].GetValue())
28 |
29 | require.Len(t, adapter.GetResult().GetLabels(allure.Suite), 1)
30 | require.Equal(t, "suiteName", adapter.GetResult().GetLabels(allure.Suite)[0].GetValue())
31 |
32 | require.Len(t, adapter.GetResult().GetLabels(allure.Package), 1)
33 | require.Equal(t, "packageName", adapter.GetResult().GetLabels(allure.Package)[0].GetValue())
34 |
35 | require.Len(t, adapter.GetResult().GetLabels(allure.Tag), 2)
36 | require.Equal(t, "tag1", adapter.GetResult().GetLabels(allure.Tag)[0].GetValue())
37 | require.Equal(t, "tag2", adapter.GetResult().GetLabels(allure.Tag)[1].GetValue())
38 |
39 | }
40 |
41 | func TestTestAdapter_GetResult(t *testing.T) {
42 | test := &allure.Result{}
43 | adapter := TestAdapter{result: test}
44 | require.Equal(t, test, adapter.GetResult())
45 | }
46 |
47 | func TestTestAdapter_SetResult(t *testing.T) {
48 | test := &allure.Result{}
49 | adapter := TestAdapter{}
50 | adapter.SetResult(test)
51 | require.Equal(t, test, adapter.GetResult())
52 | }
53 |
54 | func TestTestAdapter_SetBeforeEach(t *testing.T) {
55 | adapter := TestAdapter{}
56 | adapter.SetBeforeEach(func(t provider.T) {})
57 | require.NotNil(t, adapter.GetBeforeEach())
58 | }
59 |
60 | func TestTestAdapter_SetAfterEach(t *testing.T) {
61 | adapter := TestAdapter{}
62 | adapter.SetAfterEach(func(t provider.T) {})
63 | require.NotNil(t, adapter.GetAfterEach())
64 | }
65 |
66 | func TestTestAdapter_GetBeforeEach(t *testing.T) {
67 | adapter := TestAdapter{beforeEach: func(t provider.T) {}}
68 | require.NotNil(t, adapter.GetBeforeEach())
69 | }
70 |
71 | func TestTestAdapter_GetAfterEach(t *testing.T) {
72 | adapter := TestAdapter{afterEach: func(t provider.T) {}}
73 | require.NotNil(t, adapter.GetAfterEach())
74 | }
75 |
76 | func TestTestAdapter_GetContainer(t *testing.T) {
77 | container := allure.NewContainer()
78 | adapter := TestAdapter{container: container}
79 | require.Equal(t, container, adapter.container)
80 | }
81 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/ctx/hooks.go:
--------------------------------------------------------------------------------
1 | package ctx
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/ozontech/allure-go/pkg/allure"
7 | "github.com/ozontech/allure-go/pkg/framework/core/constants"
8 | "github.com/ozontech/allure-go/pkg/framework/provider"
9 | )
10 |
11 | type hooksCtx struct {
12 | name string
13 | container *allure.Container
14 | }
15 |
16 | // NewAfterAllCtx returns after all context
17 | func NewAfterAllCtx(container *allure.Container) provider.ExecutionContext {
18 | return &hooksCtx{container: container, name: constants.AfterAllContextName}
19 | }
20 |
21 | // NewAfterEachCtx returns after each context
22 | func NewAfterEachCtx(container *allure.Container) provider.ExecutionContext {
23 | return &hooksCtx{container: container, name: constants.AfterEachContextName}
24 | }
25 |
26 | // NewBeforeAllCtx returns before all context
27 | func NewBeforeAllCtx(container *allure.Container) provider.ExecutionContext {
28 | return &hooksCtx{container: container, name: constants.BeforeAllContextName}
29 | }
30 |
31 | // NewBeforeEachCtx returns before each context
32 | func NewBeforeEachCtx(result *allure.Container) provider.ExecutionContext {
33 | return &hooksCtx{container: result, name: constants.BeforeEachContextName}
34 | }
35 |
36 | // AddStep adds step to current execution container
37 | func (ctx *hooksCtx) AddStep(newStep *allure.Step) {
38 | switch ctx.name {
39 | case constants.BeforeAllContextName, constants.BeforeEachContextName:
40 | ctx.container.Befores = append(ctx.container.Befores, newStep)
41 |
42 | case constants.AfterAllContextName, constants.AfterEachContextName:
43 | ctx.container.Afters = append(ctx.container.Afters, newStep)
44 | }
45 | }
46 |
47 | // GetName returns context name
48 | func (ctx *hooksCtx) GetName() string {
49 | return ctx.name
50 | }
51 |
52 | // AddAttachments adds attachment to the execution context
53 | func (ctx *hooksCtx) AddAttachments(attachments ...*allure.Attachment) {
54 | if len(attachments) == 0 {
55 | return
56 | }
57 |
58 | first := attachments[0]
59 |
60 | newStep := allure.NewSimpleStep(
61 | fmt.Sprintf("Attachment %s", first.Name),
62 | allure.NewParameter("name", first.Name),
63 | allure.NewParameter("type", string(first.Type)),
64 | allure.NewParameter("source", first.Source),
65 | ).WithAttachments(attachments...)
66 |
67 | ctx.AddStep(newStep)
68 | }
69 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/ctx/hooks_test.go:
--------------------------------------------------------------------------------
1 | package ctx
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/require"
7 |
8 | "github.com/ozontech/allure-go/pkg/allure"
9 | "github.com/ozontech/allure-go/pkg/framework/core/constants"
10 | )
11 |
12 | func TestNewAfterAllCtx(t *testing.T) {
13 | ctx := NewAfterAllCtx(allure.NewContainer())
14 | require.NotNil(t, ctx)
15 | }
16 |
17 | func TestNewAfterEachCtx(t *testing.T) {
18 | ctx := NewAfterEachCtx(allure.NewContainer())
19 | require.NotNil(t, ctx)
20 | }
21 |
22 | func TestNewBeforeEachCtx(t *testing.T) {
23 | ctx := NewBeforeEachCtx(allure.NewContainer())
24 | require.NotNil(t, ctx)
25 | }
26 |
27 | func TestNewBeforeAllCtx(t *testing.T) {
28 | ctx := NewBeforeAllCtx(allure.NewContainer())
29 | require.NotNil(t, ctx)
30 | }
31 |
32 | func TestHooksCtx_GetName(t *testing.T) {
33 | th := hooksCtx{name: "test"}
34 | require.Equal(t, "test", th.GetName())
35 | }
36 |
37 | func TestHooksCtx_AddStep(t *testing.T) {
38 | testStep := allure.NewSimpleStep("test")
39 | beforeEach := hooksCtx{name: constants.BeforeEachContextName, container: &allure.Container{}}
40 | beforeEach.AddStep(testStep)
41 | require.NotEmpty(t, beforeEach.container.Befores)
42 | require.Len(t, beforeEach.container.Befores, 1)
43 | require.Equal(t, testStep, beforeEach.container.Befores[0])
44 |
45 | beforeAll := hooksCtx{name: constants.BeforeAllContextName, container: &allure.Container{}}
46 | beforeAll.AddStep(testStep)
47 | require.NotEmpty(t, beforeAll.container.Befores)
48 | require.Len(t, beforeAll.container.Befores, 1)
49 | require.Equal(t, testStep, beforeAll.container.Befores[0])
50 |
51 | afterEach := hooksCtx{name: constants.AfterEachContextName, container: &allure.Container{}}
52 | afterEach.AddStep(testStep)
53 | require.NotEmpty(t, afterEach.container.Afters)
54 | require.Len(t, afterEach.container.Afters, 1)
55 | require.Equal(t, testStep, afterEach.container.Afters[0])
56 |
57 | afterAll := hooksCtx{name: constants.AfterAllContextName, container: &allure.Container{}}
58 | afterAll.AddStep(testStep)
59 | require.NotEmpty(t, afterAll.container.Afters)
60 | require.Len(t, afterAll.container.Afters, 1)
61 | require.Equal(t, testStep, afterAll.container.Afters[0])
62 | }
63 |
64 | func TestHooksCtx_AddAttachment(t *testing.T) {
65 | attach := allure.NewAttachment("testAttach", allure.Text, []byte("test"))
66 | beforeAll := hooksCtx{name: constants.BeforeAllContextName, container: &allure.Container{}}
67 | beforeAll.AddAttachments(attach)
68 | require.NotEmpty(t, beforeAll.container.Befores)
69 | require.Len(t, beforeAll.container.Befores, 1)
70 | require.NotEmpty(t, beforeAll.container.Befores[0].Attachments)
71 | require.Len(t, beforeAll.container.Befores[0].Attachments, 1)
72 | require.Equal(t, attach, beforeAll.container.Befores[0].Attachments[0])
73 |
74 | beforeEach := hooksCtx{name: constants.BeforeEachContextName, container: &allure.Container{}}
75 | beforeEach.AddAttachments(attach)
76 | require.NotEmpty(t, beforeEach.container.Befores)
77 | require.Len(t, beforeEach.container.Befores, 1)
78 | require.NotEmpty(t, beforeEach.container.Befores[0].Attachments)
79 | require.Len(t, beforeEach.container.Befores[0].Attachments, 1)
80 | require.Equal(t, attach, beforeEach.container.Befores[0].Attachments[0])
81 |
82 | afterAll := hooksCtx{name: constants.AfterAllContextName, container: &allure.Container{}}
83 | afterAll.AddAttachments(attach)
84 | require.NotEmpty(t, afterAll.container.Afters)
85 | require.Len(t, afterAll.container.Afters, 1)
86 | require.NotEmpty(t, afterAll.container.Afters[0].Attachments)
87 | require.Len(t, afterAll.container.Afters[0].Attachments, 1)
88 | require.Equal(t, attach, afterAll.container.Afters[0].Attachments[0])
89 |
90 | afterEach := hooksCtx{name: constants.AfterEachContextName, container: &allure.Container{}}
91 | afterEach.AddAttachments(attach)
92 | require.NotEmpty(t, afterEach.container.Afters)
93 | require.Len(t, afterEach.container.Afters, 1)
94 | require.NotEmpty(t, afterEach.container.Afters[0].Attachments)
95 | require.Len(t, afterEach.container.Afters[0].Attachments, 1)
96 | require.Equal(t, attach, afterEach.container.Afters[0].Attachments[0])
97 | }
98 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/ctx/test_ctx.go:
--------------------------------------------------------------------------------
1 | package ctx
2 |
3 | import (
4 | "github.com/ozontech/allure-go/pkg/allure"
5 | "github.com/ozontech/allure-go/pkg/framework/core/constants"
6 | "github.com/ozontech/allure-go/pkg/framework/provider"
7 | )
8 |
9 | type testCtx struct {
10 | name string
11 |
12 | result *allure.Result
13 | }
14 |
15 | func NewTestCtx(result *allure.Result) provider.ExecutionContext {
16 | return &testCtx{result: result, name: constants.TestContextName}
17 | }
18 |
19 | func (ctx *testCtx) AddStep(newStep *allure.Step) {
20 | ctx.result.Steps = append(ctx.result.Steps, newStep)
21 | }
22 |
23 | func (ctx *testCtx) GetName() string {
24 | return ctx.name
25 | }
26 |
27 | func (ctx *testCtx) AddAttachments(attachments ...*allure.Attachment) {
28 | ctx.result.Attachments = append(ctx.result.Attachments, attachments...)
29 | }
30 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/ctx/test_ctx_test.go:
--------------------------------------------------------------------------------
1 | package ctx
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/ozontech/allure-go/pkg/allure"
7 | "github.com/ozontech/allure-go/pkg/framework/core/constants"
8 | "github.com/stretchr/testify/require"
9 | )
10 |
11 | func TestNewTestCtx(t *testing.T) {
12 | ctx := NewTestCtx(&allure.Result{})
13 | require.NotNil(t, ctx)
14 | }
15 |
16 | func TestTestCtx_GetName(t *testing.T) {
17 | th := testCtx{name: "test"}
18 | require.Equal(t, "test", th.GetName())
19 | }
20 |
21 | func TestTestCtx_AddStep(t *testing.T) {
22 | testStep := allure.NewSimpleStep("test")
23 | test := testCtx{name: constants.TestContextName, result: &allure.Result{}}
24 | test.AddStep(testStep)
25 | require.NotEmpty(t, test.result.Steps)
26 | require.Len(t, test.result.Steps, 1)
27 | require.Equal(t, testStep, test.result.Steps[0])
28 | }
29 |
30 | func TestTestCtx_AddAttachment(t *testing.T) {
31 | attach := allure.NewAttachment("testAttach", allure.Text, []byte("test"))
32 | test := testCtx{name: constants.TestContextName, result: &allure.Result{}}
33 | test.AddAttachments(attach)
34 | require.NotEmpty(t, test.result.Attachments)
35 | require.Len(t, test.result.Attachments, 1)
36 | require.Equal(t, attach, test.result.Attachments[0])
37 | }
38 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/attachment.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import "github.com/ozontech/allure-go/pkg/allure"
4 |
5 | // WithAttachments adds attachment to report in case of current execution context
6 | func (a *allureManager) WithAttachments(attachments ...*allure.Attachment) {
7 | a.ExecutionContext().AddAttachments(attachments...)
8 | }
9 |
10 | // WithNewAttachment creates and adds attachment to report in case of current execution context
11 | func (a *allureManager) WithNewAttachment(name string, mimeType allure.MimeType, content []byte) {
12 | a.ExecutionContext().AddAttachments(allure.NewAttachment(name, mimeType, content))
13 | }
14 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/attachment_test.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/ozontech/allure-go/pkg/allure"
7 | "github.com/ozontech/allure-go/pkg/framework/core/constants"
8 | "github.com/stretchr/testify/require"
9 | )
10 |
11 | type execMockAttach struct {
12 | name string
13 | steps []*allure.Step
14 | attach []*allure.Attachment
15 | }
16 |
17 | func newExecMockAttach(name string) *execMockAttach {
18 | return &execMockAttach{
19 | name: name,
20 | steps: make([]*allure.Step, 0),
21 | attach: make([]*allure.Attachment, 0),
22 | }
23 | }
24 |
25 | func (m *execMockAttach) AddStep(step *allure.Step) {
26 | m.steps = append(m.steps, step)
27 | }
28 |
29 | func (m *execMockAttach) AddAttachments(attachments ...*allure.Attachment) {
30 | m.attach = append(m.attach, attachments...)
31 | }
32 |
33 | func (m *execMockAttach) GetName() string {
34 | return m.name
35 | }
36 |
37 | func TestAllureManager_Attachment(t *testing.T) {
38 | mock := newExecMockAttach(constants.TestContextName)
39 | attach := allure.NewAttachment("testAttach", allure.Text, []byte("test"))
40 | manager := allureManager{executionContext: mock}
41 |
42 | manager.WithAttachments(attach)
43 | require.NotEmpty(t, mock.attach)
44 | require.Len(t, mock.attach, 1)
45 | require.Equal(t, mock.attach[0], attach)
46 | }
47 |
48 | func TestAllureManager_NewAttachment(t *testing.T) {
49 | mock := newExecMockAttach(constants.TestContextName)
50 | manager := allureManager{executionContext: mock}
51 | manager.WithNewAttachment("testAttach", allure.Text, []byte("test"))
52 | require.NotEmpty(t, mock.attach)
53 | require.Len(t, mock.attach, 1)
54 | require.Equal(t, "testAttach", mock.attach[0].Name)
55 | require.Equal(t, allure.Text, mock.attach[0].Type)
56 | require.Equal(t, []byte("test"), mock.attach[0].GetContent())
57 | }
58 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/description.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/ozontech/allure-go/pkg/allure"
7 | )
8 |
9 | // Title changes default test name to title(using fmt.Sprint)
10 | func (a *allureManager) Title(args ...interface{}) {
11 | a.withResult(func(r *allure.Result) {
12 | r.Name = fmt.Sprint(args...)
13 | })
14 | }
15 |
16 | // Titlef changes default test name to title(using fmt.Sprintf)
17 | func (a *allureManager) Titlef(format string, args ...interface{}) {
18 | a.withResult(func(r *allure.Result) {
19 | r.Name = fmt.Sprintf(format, args...)
20 | })
21 | }
22 |
23 | // Description provides description to test result(using fmt.Sprint)
24 | func (a *allureManager) Description(args ...interface{}) {
25 | a.withResult(func(r *allure.Result) {
26 | r.Description = fmt.Sprint(args...)
27 | })
28 | }
29 |
30 | // Descriptionf provides description to test result(using fmt.Sprintf)
31 | func (a *allureManager) Descriptionf(format string, args ...interface{}) {
32 | a.withResult(func(r *allure.Result) {
33 | r.Description = fmt.Sprintf(format, args...)
34 | })
35 | }
36 |
37 | // Stage provides staqe to test result(using fmt.Sprint)
38 | func (a *allureManager) Stage(args ...interface{}) {
39 | a.withResult(func(r *allure.Result) {
40 | r.Stage = fmt.Sprint(args...)
41 | })
42 | }
43 |
44 | // Stagef provides staqe to test result(using fmt.Sprintf)
45 | func (a *allureManager) Stagef(format string, args ...interface{}) {
46 | a.withResult(func(r *allure.Result) {
47 | r.Stage = fmt.Sprintf(format, args...)
48 | })
49 | }
50 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/description_test.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/ozontech/allure-go/pkg/allure"
7 | "github.com/ozontech/allure-go/pkg/framework/provider"
8 | "github.com/stretchr/testify/require"
9 | )
10 |
11 | type testMetaMockDescription struct {
12 | result *allure.Result
13 | container *allure.Container
14 | be func(t provider.T)
15 | ae func(t provider.T)
16 | }
17 |
18 | func (m *testMetaMockDescription) GetResult() *allure.Result {
19 | return m.result
20 | }
21 |
22 | func (m *testMetaMockDescription) SetResult(result *allure.Result) {
23 | m.result = result
24 | }
25 |
26 | func (m *testMetaMockDescription) GetContainer() *allure.Container {
27 | return m.container
28 | }
29 |
30 | func (m *testMetaMockDescription) SetBeforeEach(hook func(t provider.T)) {
31 | m.be = hook
32 | }
33 |
34 | func (m *testMetaMockDescription) GetBeforeEach() func(t provider.T) {
35 | return m.be
36 | }
37 |
38 | func (m *testMetaMockDescription) SetAfterEach(hook func(t provider.T)) {
39 | m.ae = hook
40 | }
41 |
42 | func (m *testMetaMockDescription) GetAfterEach() func(t provider.T) {
43 | return m.ae
44 | }
45 |
46 | func TestAllureManager_Title(t *testing.T) {
47 | manager := allureManager{testMeta: &testMetaMockDescription{result: &allure.Result{}}}
48 | manager.Title("Test")
49 | require.Equal(t, "Test", manager.testMeta.GetResult().Name)
50 | }
51 |
52 | func TestAllureManager_Description(t *testing.T) {
53 | manager := allureManager{testMeta: &testMetaMockDescription{result: &allure.Result{}}}
54 | manager.Description("Test")
55 | require.Equal(t, "Test", manager.testMeta.GetResult().Description)
56 | }
57 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/execution_management.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import "github.com/ozontech/allure-go/pkg/framework/core/allure_manager/ctx"
4 |
5 | // TestContext initiate test context
6 | func (a *allureManager) TestContext() {
7 | a.executionContext = ctx.NewTestCtx(a.testMeta.GetResult())
8 | }
9 |
10 | // BeforeEachContext initiate before each context
11 | func (a *allureManager) BeforeEachContext() {
12 | a.executionContext = ctx.NewBeforeEachCtx(a.testMeta.GetContainer())
13 | }
14 |
15 | // AfterEachContext initiate after each context
16 | func (a *allureManager) AfterEachContext() {
17 | a.executionContext = ctx.NewAfterEachCtx(a.testMeta.GetContainer())
18 | }
19 |
20 | // BeforeAllContext initiate before all context
21 | func (a *allureManager) BeforeAllContext() {
22 | a.executionContext = ctx.NewBeforeAllCtx(a.suiteMeta.GetContainer())
23 | }
24 |
25 | // AfterAllContext initiate after all context
26 | func (a *allureManager) AfterAllContext() {
27 | a.executionContext = ctx.NewAfterAllCtx(a.suiteMeta.GetContainer())
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/execution_management_test.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/ozontech/allure-go/pkg/allure"
7 | "github.com/ozontech/allure-go/pkg/framework/core/constants"
8 | "github.com/ozontech/allure-go/pkg/framework/provider"
9 | "github.com/stretchr/testify/require"
10 | )
11 |
12 | type testMetaMockExecM struct {
13 | result *allure.Result
14 | container *allure.Container
15 | be func(t provider.T)
16 | ae func(t provider.T)
17 | }
18 |
19 | func (m *testMetaMockExecM) GetResult() *allure.Result {
20 | return m.result
21 | }
22 |
23 | func (m *testMetaMockExecM) SetResult(result *allure.Result) {
24 | m.result = result
25 | }
26 |
27 | func (m *testMetaMockExecM) GetContainer() *allure.Container {
28 | return m.container
29 | }
30 |
31 | func (m *testMetaMockExecM) SetBeforeEach(hook func(t provider.T)) {
32 | m.be = hook
33 | }
34 |
35 | func (m *testMetaMockExecM) GetBeforeEach() func(t provider.T) {
36 | return m.be
37 | }
38 |
39 | func (m *testMetaMockExecM) SetAfterEach(hook func(t provider.T)) {
40 | m.ae = hook
41 | }
42 |
43 | func (m *testMetaMockExecM) GetAfterEach() func(t provider.T) {
44 | return m.ae
45 | }
46 |
47 | type suiteMetaMockExecM struct {
48 | name string
49 | container *allure.Container
50 | hook func(t provider.T)
51 | }
52 |
53 | func (m *suiteMetaMockExecM) GetPackageName() string {
54 | return m.name
55 | }
56 |
57 | func (m *suiteMetaMockExecM) GetRunner() string {
58 | return m.name
59 | }
60 |
61 | func (m *suiteMetaMockExecM) GetSuiteName() string {
62 | return m.name
63 | }
64 |
65 | func (m *suiteMetaMockExecM) GetParentSuite() string {
66 | return ""
67 | }
68 |
69 | func (m *suiteMetaMockExecM) GetSuiteFullName() string {
70 | return m.name
71 | }
72 |
73 | func (m *suiteMetaMockExecM) GetContainer() *allure.Container {
74 | return m.container
75 | }
76 |
77 | func (m *suiteMetaMockExecM) SetBeforeAll(hook func(provider.T)) {
78 | m.hook = hook
79 | }
80 |
81 | func (m *suiteMetaMockExecM) SetAfterAll(hook func(provider.T)) {
82 | m.hook = hook
83 | }
84 |
85 | func (m *suiteMetaMockExecM) GetBeforeAll() func(provider.T) {
86 | return m.hook
87 | }
88 |
89 | func (m *suiteMetaMockExecM) GetAfterAll() func(provider.T) {
90 | return m.hook
91 | }
92 |
93 | func TestAllureManager_AfterAllContext(t *testing.T) {
94 | manager := allureManager{suiteMeta: &suiteMetaMockExecM{container: allure.NewContainer()}}
95 | manager.AfterAllContext()
96 | require.NotNil(t, manager.executionContext)
97 | require.Equal(t, constants.AfterAllContextName, manager.executionContext.GetName())
98 | }
99 |
100 | func TestAllureManager_BeforeAllContext(t *testing.T) {
101 | manager := allureManager{suiteMeta: &suiteMetaMockExecM{container: allure.NewContainer()}}
102 | manager.BeforeAllContext()
103 | require.NotNil(t, manager.executionContext)
104 | require.Equal(t, constants.BeforeAllContextName, manager.executionContext.GetName())
105 | }
106 |
107 | func TestAllureManager_BeforeEachContext(t *testing.T) {
108 | manager := allureManager{testMeta: &testMetaMockExecM{container: allure.NewContainer()}}
109 | manager.BeforeEachContext()
110 | require.NotNil(t, manager.executionContext)
111 | require.Equal(t, constants.BeforeEachContextName, manager.executionContext.GetName())
112 | }
113 |
114 | func TestAllureManager_AfterEachContext(t *testing.T) {
115 | manager := allureManager{testMeta: &testMetaMockExecM{container: allure.NewContainer()}}
116 | manager.AfterEachContext()
117 | require.NotNil(t, manager.executionContext)
118 | require.Equal(t, constants.AfterEachContextName, manager.executionContext.GetName())
119 | }
120 |
121 | func TestAllureManager_TestContext(t *testing.T) {
122 | manager := allureManager{testMeta: &testMetaMockExecM{result: &allure.Result{}}}
123 | manager.TestContext()
124 | require.NotNil(t, manager.executionContext)
125 | require.Equal(t, constants.TestContextName, manager.executionContext.GetName())
126 | }
127 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/labels.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import (
4 | "github.com/ozontech/allure-go/pkg/allure"
5 | )
6 |
7 | /*
8 | Labels
9 | */
10 |
11 | // Label provides possibility to add any Label to test result
12 | func (a *allureManager) Label(label *allure.Label) {
13 | a.withResult(func(r *allure.Result) {
14 | r.Labels = append(r.Labels, label)
15 | })
16 | }
17 |
18 | // Labels provides possibility to add few Labels to test result
19 | func (a *allureManager) Labels(labels ...*allure.Label) {
20 | a.withResult(func(r *allure.Result) {
21 | r.Labels = append(r.Labels, labels...)
22 | })
23 | }
24 |
25 | func (a *allureManager) ReplaceLabel(label *allure.Label) {
26 | a.withResult(func(r *allure.Result) {
27 | for _, l := range r.Labels {
28 | if l.Name == label.Name {
29 | l.Value = label.Value
30 |
31 | return
32 | }
33 | }
34 |
35 | a.Label(label)
36 | })
37 | }
38 |
39 | // Epic adds Epic label to test result
40 | func (a *allureManager) Epic(value string) {
41 | a.Label(allure.EpicLabel(value))
42 | }
43 |
44 | // Layer adds Layer label to test result
45 | func (a *allureManager) Layer(value string) {
46 | a.Label(allure.LayerLabel(value))
47 | }
48 |
49 | // Feature adds Feature label to test result
50 | func (a *allureManager) Feature(value string) {
51 | a.Label(allure.FeatureLabel(value))
52 | }
53 |
54 | // Story adds Story label to test result
55 | func (a *allureManager) Story(value string) {
56 | a.Label(allure.StoryLabel(value))
57 | }
58 |
59 | // FrameWork adds FrameWork label to test result
60 | func (a *allureManager) FrameWork(value string) {
61 | a.ReplaceLabel(allure.FrameWorkLabel(value))
62 | }
63 |
64 | // Host adds Host label to test result
65 | func (a *allureManager) Host(value string) {
66 | a.ReplaceLabel(allure.HostLabel(value))
67 | }
68 |
69 | // Thread adds Thread label to test result
70 | // Seems like there is no way to access an identifier for the current goroutine in Go.
71 | func (a *allureManager) Thread(value string) {
72 | a.ReplaceLabel(allure.ThreadLabel(value))
73 | }
74 |
75 | // ID adds ID label to test result
76 | func (a *allureManager) ID(value string) {
77 | a.ReplaceLabel(allure.IDLabel(value))
78 | }
79 |
80 | // Language adds Language label to test result
81 | func (a *allureManager) Language(value string) {
82 | a.ReplaceLabel(allure.LanguageLabel(value))
83 | }
84 |
85 | // AddSuiteLabel adds suite label to test result
86 | func (a *allureManager) AddSuiteLabel(value string) {
87 | a.Label(allure.SuiteLabel(value))
88 | }
89 |
90 | // AddSubSuite adds AddSubSuite label to test result
91 | func (a *allureManager) AddSubSuite(value string) {
92 | a.Label(allure.SubSuiteLabel(value))
93 | }
94 |
95 | // AddParentSuite adds AddParentSuite label to test result
96 | func (a *allureManager) AddParentSuite(value string) {
97 | a.Label(allure.ParentSuiteLabel(value))
98 | }
99 |
100 | // Severity adds Severity label to test result
101 | func (a *allureManager) Severity(value allure.SeverityType) {
102 | a.ReplaceLabel(allure.SeverityLabel(value))
103 | }
104 |
105 | // Tag adds Tag label to test result
106 | func (a *allureManager) Tag(value string) {
107 | a.Label(allure.TagLabel(value))
108 | }
109 |
110 | // Tags adds a multiple Tag label to test result
111 | func (a *allureManager) Tags(values ...string) {
112 | a.Labels(allure.TagLabels(values...)...)
113 | }
114 |
115 | // Package adds Package label to test result
116 | func (a *allureManager) Package(value string) {
117 | a.ReplaceLabel(allure.PackageLabel(value))
118 | }
119 |
120 | // Owner adds Owner label to test result
121 | func (a *allureManager) Owner(value string) {
122 | a.Label(allure.OwnerLabel(value))
123 | }
124 |
125 | // Lead adds Lead label to test result
126 | func (a *allureManager) Lead(value string) {
127 | a.Label(allure.LeadLabel(value))
128 | }
129 |
130 | func (a *allureManager) AllureID(value string) {
131 | a.ReplaceLabel(allure.IDAllureLabel(value))
132 | }
133 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/links.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import (
4 | "github.com/ozontech/allure-go/pkg/allure"
5 | )
6 |
7 | // SetIssue adds issue link due environment variable ALLURE_ISSUE_PATTERN
8 | func (a *allureManager) SetIssue(issue string) {
9 | a.Link(allure.IssueLink(issue))
10 | }
11 |
12 | // SetTestCase adds test case link due environment variable ALLURE_TESTCASE_PATTERN
13 | func (a *allureManager) SetTestCase(testCase string) {
14 | a.Link(allure.TestCaseLink(testCase))
15 | }
16 |
17 | // TmsLink adds allure external test case link due environment variable ALLURE_TMS_LINK_PATTERN
18 | func (a *allureManager) TmsLink(testCase string) {
19 | a.Link(allure.TmsLink(testCase))
20 | }
21 |
22 | // TmsLinks adds multiple external test case links due environment variable ALLURE_TMS_LINK_PATTERN
23 | func (a *allureManager) TmsLinks(testCase ...string) {
24 | a.Links(allure.TmsLinks(testCase...))
25 | }
26 |
27 | // Link adds Link to struct.AllureResult
28 | func (a *allureManager) Link(link *allure.Link) {
29 | a.withResult(func(r *allure.Result) {
30 | r.Links = append(r.Links, link)
31 | })
32 | }
33 |
34 | // Links adds multiple Link to struct.AllureResult
35 | func (a *allureManager) Links(links []*allure.Link) {
36 | a.withResult(func(r *allure.Result) {
37 | r.Links = append(r.Links, links...)
38 | })
39 | }
40 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/links_test.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/ozontech/allure-go/pkg/allure"
7 | "github.com/ozontech/allure-go/pkg/framework/provider"
8 | "github.com/stretchr/testify/require"
9 | )
10 |
11 | type testMetaMockLinks struct {
12 | result *allure.Result
13 | container *allure.Container
14 | be func(t provider.T)
15 | ae func(t provider.T)
16 | }
17 |
18 | func (m *testMetaMockLinks) GetResult() *allure.Result {
19 | return m.result
20 | }
21 |
22 | func (m *testMetaMockLinks) SetResult(result *allure.Result) {
23 | m.result = result
24 | }
25 |
26 | func (m *testMetaMockLinks) GetContainer() *allure.Container {
27 | return m.container
28 | }
29 |
30 | func (m *testMetaMockLinks) SetBeforeEach(hook func(t provider.T)) {
31 | m.be = hook
32 | }
33 |
34 | func (m *testMetaMockLinks) GetBeforeEach() func(t provider.T) {
35 | return m.be
36 | }
37 |
38 | func (m *testMetaMockLinks) SetAfterEach(hook func(t provider.T)) {
39 | m.ae = hook
40 | }
41 |
42 | func (m *testMetaMockLinks) GetAfterEach() func(t provider.T) {
43 | return m.ae
44 | }
45 |
46 | func TestAllureManager_Link(t *testing.T) {
47 | manager := allureManager{testMeta: &testMetaMockLinks{result: &allure.Result{}}}
48 | manager.Link(allure.NewLink("Name", allure.LINK, "http://test.com"))
49 | require.Len(t, manager.GetResult().Links, 1)
50 | require.Equal(t, "Name", manager.GetResult().Links[0].Name)
51 | require.Equal(t, string(allure.LINK), manager.GetResult().Links[0].Type)
52 | require.Equal(t, "http://test.com", manager.GetResult().Links[0].URL)
53 |
54 | }
55 |
56 | func TestAllureManager_SetTestCase(t *testing.T) {
57 | manager := allureManager{testMeta: &testMetaMockLinks{result: &allure.Result{}}}
58 | manager.SetTestCase("TestCase")
59 | require.Len(t, manager.GetResult().Links, 1)
60 | require.Equal(t, "TestCase[TestCase]", manager.GetResult().Links[0].Name)
61 | require.Equal(t, string(allure.TESTCASE), manager.GetResult().Links[0].Type)
62 | }
63 |
64 | func TestAllureManager_SetIssue(t *testing.T) {
65 | manager := allureManager{testMeta: &testMetaMockLinks{result: &allure.Result{}}}
66 | manager.SetIssue("Issue")
67 | require.NotEmpty(t, manager.GetResult().Links)
68 | require.Len(t, manager.GetResult().Links, 1)
69 | require.Equal(t, "Issue[Issue]", manager.GetResult().Links[0].Name)
70 | require.Equal(t, string(allure.ISSUE), manager.GetResult().Links[0].Type)
71 | }
72 |
73 | func TestAllureManager_TmsLink(t *testing.T) {
74 | manager := allureManager{testMeta: &testMetaMockLinks{result: &allure.Result{}}}
75 | manager.TmsLink("TmsLink")
76 | require.NotEmpty(t, manager.GetResult().Links)
77 | require.Len(t, manager.GetResult().Links, 1)
78 | require.Equal(t, "TmsLink", manager.GetResult().Links[0].Name)
79 | require.Equal(t, string(allure.TMS), manager.GetResult().Links[0].Type)
80 | }
81 |
82 | func TestAllureManager_TmsLinks(t *testing.T) {
83 | manager := allureManager{testMeta: &testMetaMockLinks{result: &allure.Result{}}}
84 | manager.TmsLinks("TmsLink1", "TmsLink2")
85 | require.NotEmpty(t, manager.GetResult().Links)
86 | require.Len(t, manager.GetResult().Links, 2)
87 | require.Equal(t, "TmsLink1", manager.GetResult().Links[0].Name)
88 | require.Equal(t, "TmsLink2", manager.GetResult().Links[1].Name)
89 | require.Equal(t, string(allure.TMS), manager.GetResult().Links[0].Type)
90 | require.Equal(t, string(allure.TMS), manager.GetResult().Links[1].Type)
91 | }
92 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/parameter.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import "github.com/ozontech/allure-go/pkg/allure"
4 |
5 | // WithParameters adds parameters to report in case of current execution context
6 | func (a *allureManager) WithParameters(params ...*allure.Parameter) {
7 | a.withResult(func(r *allure.Result) {
8 | r.Parameters = append(r.Parameters, params...)
9 | })
10 | }
11 |
12 | // WithNewParameters adds parameters to report in case of current execution context
13 | func (a *allureManager) WithNewParameters(kv ...interface{}) {
14 | a.withResult(func(r *allure.Result) {
15 | r.Parameters = append(r.Parameters, allure.NewParameters(kv...)...)
16 | })
17 | }
18 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/parameter_test.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/ozontech/allure-go/pkg/allure"
7 | "github.com/ozontech/allure-go/pkg/framework/provider"
8 | "github.com/stretchr/testify/require"
9 | )
10 |
11 | type testMetaMockParameter struct {
12 | result *allure.Result
13 | container *allure.Container
14 | be func(t provider.T)
15 | ae func(t provider.T)
16 | }
17 |
18 | func (m *testMetaMockParameter) GetResult() *allure.Result {
19 | return m.result
20 | }
21 |
22 | func (m *testMetaMockParameter) SetResult(result *allure.Result) {
23 | m.result = result
24 | }
25 |
26 | func (m *testMetaMockParameter) GetContainer() *allure.Container {
27 | return m.container
28 | }
29 |
30 | func (m *testMetaMockParameter) SetBeforeEach(hook func(t provider.T)) {
31 | m.be = hook
32 | }
33 |
34 | func (m *testMetaMockParameter) GetBeforeEach() func(t provider.T) {
35 | return m.be
36 | }
37 |
38 | func (m *testMetaMockParameter) SetAfterEach(hook func(t provider.T)) {
39 | m.ae = hook
40 | }
41 |
42 | func (m *testMetaMockParameter) GetAfterEach() func(t provider.T) {
43 | return m.ae
44 | }
45 |
46 | func TestAllureManager_Parameter(t *testing.T) {
47 | manager := allureManager{testMeta: &testMetaMockParameter{result: &allure.Result{}}}
48 | manager.WithParameters(allure.NewParameter("host", "localhost"))
49 | require.Len(t, manager.GetResult().Parameters, 1)
50 | require.Equal(t, "host", manager.GetResult().Parameters[0].Name)
51 | require.Equal(t, "localhost", manager.GetResult().Parameters[0].GetValue())
52 | }
53 |
54 | func TestAllureManager_NewParameter(t *testing.T) {
55 | manager := allureManager{testMeta: &testMetaMockParameter{result: &allure.Result{}}}
56 | manager.WithNewParameters("host", "localhost", "os", "linux")
57 | require.Len(t, manager.GetResult().Parameters, 2)
58 | require.Equal(t, "host", manager.GetResult().Parameters[0].Name)
59 | require.Equal(t, "localhost", manager.GetResult().Parameters[0].GetValue())
60 | require.Equal(t, "os", manager.GetResult().Parameters[1].Name)
61 | require.Equal(t, "linux", manager.GetResult().Parameters[1].GetValue())
62 | }
63 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/provider.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import (
4 | "github.com/ozontech/allure-go/pkg/allure"
5 | "github.com/ozontech/allure-go/pkg/framework/core/allure_manager/adapter"
6 | "github.com/ozontech/allure-go/pkg/framework/provider"
7 | )
8 |
9 | type allureManager struct {
10 | testMeta provider.TestMeta
11 | suiteMeta provider.SuiteMeta
12 |
13 | executionContext provider.ExecutionContext
14 | }
15 |
16 | func NewProvider(cfg ProviderConfig) provider.Provider {
17 | suiteMeta := adapter.NewSuiteMetaWithParent(
18 | cfg.PackageName(),
19 | cfg.Runner(),
20 | cfg.FullName(),
21 | cfg.SuiteName(),
22 | cfg.ParentSuite(),
23 | )
24 |
25 | return &allureManager{
26 | suiteMeta: suiteMeta,
27 | testMeta: &adapter.TestAdapter{},
28 | }
29 | }
30 |
31 | func (a *allureManager) withResult(f func(r *allure.Result)) {
32 | if r := a.GetResult(); r != nil {
33 | f(r)
34 | }
35 | }
36 |
37 | func (a *allureManager) UpdateResultStatus(msg string, trace string) {
38 | a.GetResult().SetStatusMessage(msg)
39 | a.GetResult().SetStatusTrace(trace)
40 | }
41 |
42 | func (a *allureManager) StopResult(status allure.Status) {
43 | a.withResult(func(r *allure.Result) {
44 | r.Status = status
45 | r.Stop = allure.GetNow()
46 | })
47 | }
48 |
49 | func (a *allureManager) GetResult() *allure.Result {
50 | return a.testMeta.GetResult()
51 | }
52 |
53 | func (a *allureManager) SetTestMeta(meta provider.TestMeta) {
54 | a.testMeta = meta
55 | }
56 |
57 | func (a *allureManager) GetTestMeta() provider.TestMeta {
58 | return a.testMeta
59 | }
60 |
61 | func (a *allureManager) GetSuiteMeta() provider.SuiteMeta {
62 | return a.suiteMeta
63 | }
64 |
65 | func (a *allureManager) ExecutionContext() provider.ExecutionContext {
66 | return a.executionContext
67 | }
68 |
69 | func (a *allureManager) NewTest(testName, packageName string, tags ...string) {
70 | a.testMeta = adapter.NewTestMeta(
71 | a.suiteMeta.GetSuiteFullName(),
72 | a.suiteMeta.GetSuiteName(),
73 | testName,
74 | packageName,
75 | tags...,
76 | )
77 |
78 | if parentSuite := a.suiteMeta.GetParentSuite(); parentSuite != "" {
79 | a.testMeta.GetResult().WithParentSuite(parentSuite)
80 | }
81 |
82 | a.suiteMeta.GetContainer().AddChild(a.testMeta.GetResult().UUID)
83 | }
84 |
85 | func (a *allureManager) FinishTest() error {
86 | container := a.testMeta.GetContainer()
87 | if container != nil {
88 | if err := container.Done(); err != nil {
89 | return err
90 | }
91 | }
92 |
93 | return a.testMeta.GetResult().Done()
94 | }
95 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/provider_config.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | type ConfigKey string
4 |
5 | // describes base provider configs
6 | const (
7 | SuiteName ConfigKey = "suite"
8 | PackageName ConfigKey = "package"
9 | FullName ConfigKey = "fullName"
10 | SuitePath ConfigKey = "suitePath"
11 | Runner ConfigKey = "runner"
12 | ParentSuite ConfigKey = "parentSuite"
13 | )
14 |
15 | func (c ConfigKey) String() string {
16 | return string(c)
17 | }
18 |
19 | // ProviderConfig describes configuration interface
20 | type ProviderConfig interface {
21 | SuitePath() string
22 | SuiteName() string
23 | FullName() string
24 | PackageName() string
25 | ParentSuite() string
26 | Runner() string
27 |
28 | WithSuitePath(suitePath string) ProviderConfig
29 | WithSuiteName(suiteName string) ProviderConfig
30 | WithFullName(fullName string) ProviderConfig
31 | WithPackageName(packageName string) ProviderConfig
32 | WithParentSuite(parentSuite string) ProviderConfig
33 | WithRunner(runner string) ProviderConfig
34 | }
35 |
36 | type providerConfig struct {
37 | cfg map[ConfigKey]string
38 | }
39 |
40 | // NewProviderConfig ...
41 | func NewProviderConfig() ProviderConfig {
42 | return &providerConfig{make(map[ConfigKey]string)}
43 | }
44 |
45 | // SuitePath ...
46 | func (cfg *providerConfig) SuitePath() string {
47 | return cfg.cfg[SuitePath]
48 | }
49 |
50 | // SuiteName ...
51 | func (cfg *providerConfig) SuiteName() string {
52 | return cfg.cfg[SuiteName]
53 | }
54 |
55 | // PackageName ...
56 | func (cfg *providerConfig) PackageName() string {
57 | return cfg.cfg[PackageName]
58 | }
59 |
60 | // FullName ...
61 | func (cfg *providerConfig) FullName() string {
62 | return cfg.cfg[FullName]
63 | }
64 |
65 | // Runner ...
66 | func (cfg *providerConfig) Runner() string {
67 | return cfg.cfg[Runner]
68 | }
69 |
70 | // ParentSuite ...
71 | func (cfg *providerConfig) ParentSuite() string {
72 | return cfg.cfg[ParentSuite]
73 | }
74 |
75 | // WithSuitePath ...
76 | func (cfg *providerConfig) WithSuitePath(suitePath string) ProviderConfig {
77 | cfg.cfg[SuitePath] = suitePath
78 | return cfg
79 | }
80 |
81 | // WithSuiteName ...
82 | func (cfg *providerConfig) WithSuiteName(suiteName string) ProviderConfig {
83 | cfg.cfg[SuiteName] = suiteName
84 | return cfg
85 | }
86 |
87 | // WithPackageName ...
88 | func (cfg *providerConfig) WithPackageName(packageName string) ProviderConfig {
89 | cfg.cfg[PackageName] = packageName
90 | return cfg
91 | }
92 |
93 | // WithFullName ...
94 | func (cfg *providerConfig) WithFullName(fullName string) ProviderConfig {
95 | cfg.cfg[FullName] = fullName
96 | return cfg
97 | }
98 |
99 | // WithRunner ...
100 | func (cfg *providerConfig) WithRunner(runner string) ProviderConfig {
101 | cfg.cfg[Runner] = runner
102 | return cfg
103 | }
104 |
105 | // WithParentSuite ...
106 | func (cfg *providerConfig) WithParentSuite(parentSuite string) ProviderConfig {
107 | cfg.cfg[ParentSuite] = parentSuite
108 | return cfg
109 | }
110 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/provider_config_test.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/require"
7 | )
8 |
9 | func TestProviderConfigConstants(t *testing.T) {
10 | require.Equal(t, "suite", string(SuiteName))
11 | require.Equal(t, "package", string(PackageName))
12 | require.Equal(t, "fullName", string(FullName))
13 | require.Equal(t, "suitePath", string(SuitePath))
14 | require.Equal(t, "runner", string(Runner))
15 | }
16 |
17 | func TestNewProviderConfig(t *testing.T) {
18 | cfg := NewProviderConfig()
19 | require.NotNil(t, cfg)
20 | }
21 |
22 | func TestProviderConfig_values(t *testing.T) {
23 | cfg := providerConfig{map[ConfigKey]string{}}
24 |
25 | cfg.WithRunner("runner")
26 | require.NotEmpty(t, cfg.cfg[Runner])
27 | require.Equal(t, "runner", cfg.cfg[Runner])
28 | require.NotEmpty(t, cfg.Runner())
29 | require.Equal(t, "runner", cfg.Runner())
30 |
31 | cfg.WithSuiteName("suiteName")
32 | require.NotEmpty(t, cfg.cfg[SuiteName])
33 | require.Equal(t, "suiteName", cfg.cfg[SuiteName])
34 | require.NotEmpty(t, cfg.SuiteName())
35 | require.Equal(t, "suiteName", cfg.SuiteName())
36 |
37 | cfg.WithFullName("fullName")
38 | require.NotEmpty(t, cfg.cfg[FullName])
39 | require.Equal(t, "fullName", cfg.cfg[FullName])
40 | require.NotEmpty(t, cfg.FullName())
41 | require.Equal(t, "fullName", cfg.FullName())
42 |
43 | cfg.WithPackageName("packageName")
44 | require.NotEmpty(t, cfg.cfg[PackageName])
45 | require.Equal(t, "packageName", cfg.cfg[PackageName])
46 | require.NotEmpty(t, cfg.PackageName())
47 | require.Equal(t, "packageName", cfg.PackageName())
48 |
49 | cfg.WithSuitePath("suitePath")
50 | require.NotEmpty(t, cfg.cfg[SuitePath])
51 | require.Equal(t, "suitePath", cfg.cfg[SuitePath])
52 | require.NotEmpty(t, cfg.SuitePath())
53 | require.Equal(t, "suitePath", cfg.SuitePath())
54 | }
55 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/manager/steps.go:
--------------------------------------------------------------------------------
1 | package manager
2 |
3 | import (
4 | "github.com/ozontech/allure-go/pkg/allure"
5 | )
6 |
7 | // Step adds step to test result
8 | func (a *allureManager) Step(step *allure.Step) {
9 | a.ExecutionContext().AddStep(step)
10 | }
11 |
12 | // NewStep creates new step and adds it to test result
13 | func (a *allureManager) NewStep(stepName string, params ...*allure.Parameter) {
14 | a.ExecutionContext().AddStep(allure.NewSimpleStep(stepName, params...))
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/framework/core/allure_manager/testplan/testplan.go:
--------------------------------------------------------------------------------
1 | package testplan
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "os"
7 | "path/filepath"
8 | "strings"
9 | "sync"
10 | )
11 |
12 | var (
13 | once = sync.Once{}
14 | testPlan = initTestPlan()
15 | )
16 |
17 | // Path to testplan.json
18 | const testPlanPath = "ALLURE_TESTPLAN_PATH"
19 |
20 | type TestCase struct {
21 | ID int `json:"id"`
22 | Selector string `json:"selector"`
23 | }
24 |
25 | type TestPlan struct {
26 | Version string `json:"version"`
27 | Tests []*TestCase `json:"tests"`
28 | }
29 |
30 | func newTestPlan() (*TestPlan, error) {
31 | filePath := os.Getenv(testPlanPath)
32 | if filePath == "" {
33 | return nil, fmt.Errorf("{%s} environment variable not set", testPlanPath)
34 | }
35 |
36 | if filepath.Ext(filePath) != ".json" {
37 | return nil, fmt.Errorf("%s environment variable has a wrong format. Please, set path to .json file. Current path:%s", testPlanPath, filePath)
38 | }
39 |
40 | testPlanRaw, err := findTestPlan(filePath)
41 | if err != nil {
42 | return nil, err
43 | }
44 |
45 | var plan TestPlan
46 |
47 | err = json.Unmarshal(testPlanRaw, &plan)
48 | if err != nil {
49 | return nil, err
50 | }
51 |
52 | if len(plan.Tests) == 0 {
53 | return nil, fmt.Errorf("no any tests found in %s", filePath)
54 | }
55 |
56 | return &plan, nil
57 | }
58 |
59 | // IsSelected returns true if selector matches with testplan selector
60 | // TODO: ID parsing from TestOps
61 | func (p *TestPlan) IsSelected(id, selector string) bool {
62 | for _, t := range p.Tests {
63 | if t.Selector == selector {
64 | return true
65 | }
66 | }
67 |
68 | return false
69 | }
70 |
71 | func initTestPlan() *TestPlan {
72 | var (
73 | err error
74 | tPlan *TestPlan
75 | )
76 |
77 | testPlanOnce := func() {
78 | tPlan, err = newTestPlan()
79 | if err == nil {
80 | fmt.Printf("TestPlan found!")
81 | }
82 | }
83 | once.Do(testPlanOnce)
84 |
85 | return tPlan
86 | }
87 |
88 | // GetTestPlan ...
89 | func GetTestPlan() *TestPlan {
90 | return testPlan
91 | }
92 |
93 | func findTestPlan(path string) (testPlanRaw []byte, readFileErr error) {
94 | // TODO: refactor this function to use filepath pkg properly
95 |
96 | testPlanRaw, readFileErr = os.ReadFile(filepath.Clean(path))
97 | if readFileErr == nil && testPlanRaw != nil {
98 | return testPlanRaw, nil
99 | }
100 |
101 | dir, getWdErr := os.Getwd()
102 | if getWdErr != nil {
103 | return nil, getWdErr
104 | }
105 |
106 | pathParts := strings.Split(dir, string(os.PathSeparator))
107 |
108 | // windows absolute path workaround
109 | // issue describing: https://github.com/golang/go/issues/26953#issuecomment-412447719
110 | if strings.HasSuffix(pathParts[0], ":") {
111 | pathParts[0] = pathParts[0] + "/"
112 | }
113 |
114 | // os.Getwd() returns current test folder.
115 | // trying to walk up the absolute path to find testplan.json
116 | tmpPathParts := pathParts
117 | for range pathParts {
118 | basicPath := filepath.Join(tmpPathParts...)
119 | absolutePath := filepath.Join(basicPath, filepath.Clean(path))
120 | if pathParts[0] == "" && len(pathParts) > 1 {
121 | absolutePath = "/" + absolutePath
122 | }
123 |
124 | //nolint:gosec // already cleared
125 | testPlanRaw, readFileErr = os.ReadFile(absolutePath)
126 | if readFileErr != nil {
127 | // stop looking if project root found
128 | //nolint:gosec // already cleared
129 | _, gErr := os.ReadFile(filepath.Join(basicPath, "go.mod"))
130 | if gErr == nil {
131 | return
132 | }
133 | tmpPathParts = tmpPathParts[:len(tmpPathParts)-1]
134 | continue
135 | }
136 | break
137 | }
138 | return
139 | }
140 |
--------------------------------------------------------------------------------
/pkg/framework/core/assert/assertions.go:
--------------------------------------------------------------------------------
1 | package assert
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 |
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | // TestingT is an interface wrapper around *testing.T
11 | type TestingT interface {
12 | Errorf(format string, args ...interface{})
13 | }
14 |
15 | type tHelper interface {
16 | Helper()
17 | }
18 |
19 | // JSONContains asserts that expected JSON contains fields and values of actual JSON which can be bigger.
20 | //
21 | // assert.JSONContains(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world", "foobar": 1}`)
22 | func JSONContains(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
23 | if h, ok := t.(tHelper); ok {
24 | h.Helper()
25 | }
26 | var expectedJSONAsInterface, actualJSONAsInterface interface{}
27 |
28 | if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil {
29 | return assert.Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...)
30 | }
31 |
32 | if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil {
33 | return assert.Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...)
34 | }
35 |
36 | return assert.Equal(t, expectedJSONAsInterface, extractActualJSON(t, expectedJSONAsInterface, actualJSONAsInterface), msgAndArgs...)
37 | }
38 |
39 | func extractActualJSON(t TestingT, expected interface{}, actual interface{}) interface{} {
40 | switch expected.(type) {
41 | case []interface{}:
42 | exp := expected.([]interface{})
43 | act, ok := actual.([]interface{})
44 | if !ok {
45 | assert.Fail(t, "Unexpected type of actual JSON element")
46 | return nil
47 | }
48 | if len(exp) > len(act) {
49 | assert.Fail(t, "Expected slice bigger than actual JSON element")
50 | return nil
51 | }
52 | result := make([]interface{}, 0, len(exp))
53 |
54 | for i, ev := range exp {
55 | result = append(result, extractActualJSON(t, ev, act[i]))
56 | }
57 | return result
58 |
59 | case map[string]interface{}:
60 | result := make(map[string]interface{}, len(expected.(map[string]interface{})))
61 | act, ok := actual.(map[string]interface{})
62 | if !ok {
63 | assert.Fail(t, "Unexpected type of actual JSON element")
64 | return nil
65 | }
66 |
67 | for k, ev := range expected.(map[string]interface{}) { // use type assertion to loop over map[string]interface{}
68 | result[k] = extractActualJSON(t, ev, act[k])
69 | }
70 | return result
71 | }
72 | return actual
73 | }
74 |
--------------------------------------------------------------------------------
/pkg/framework/core/assert/assertions_test.go:
--------------------------------------------------------------------------------
1 | package assert
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestJSONContains_EqualSONString(t *testing.T) {
10 | mockT := new(testing.T)
11 | assert.True(t, JSONContains(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`))
12 | }
13 |
14 | func TestJSONContains_EquivalentButNotEqual(t *testing.T) {
15 | mockT := new(testing.T)
16 | assert.True(t, JSONContains(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`))
17 | }
18 |
19 | func TestJSONContains_HashOfArraysAndHashes(t *testing.T) {
20 | mockT := new(testing.T)
21 | assert.True(t, JSONContains(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}",
22 | "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}"))
23 | }
24 |
25 | func TestJSONContains_Array(t *testing.T) {
26 | mockT := new(testing.T)
27 | assert.True(t, JSONContains(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`))
28 | }
29 |
30 | func TestJSONContains_ExpectedArrayLessThanActual(t *testing.T) {
31 | mockT := new(testing.T)
32 | assert.False(t, JSONContains(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{"foobar": 1}, "foo", {"nested": "hash", "hello": "world"}]`))
33 | }
34 |
35 | func TestJSONContains_ExpectedArrayBiggerThanActual(t *testing.T) {
36 | mockT := new(testing.T)
37 | assert.False(t, JSONContains(mockT, `[{"foobar": 1}, "foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`))
38 | }
39 |
40 | func TestJSONContains_ExpectedLessThanActual(t *testing.T) {
41 | mockT := new(testing.T)
42 | assert.True(t, JSONContains(mockT, `{"hello": {"world": 1}, "foo": [{"bar": "baz"}]}`,
43 | `{"hello": {"world": 1, "missing": "key"}, "foo": [{"bar": "baz", "waldo": "fred"}], "foobar": 2}`))
44 | }
45 |
46 | func TestJSONContains_ExpectedBiggerThanActual(t *testing.T) {
47 | mockT := new(testing.T)
48 | assert.False(t, JSONContains(mockT, `{"hello": {"world": 1}, "foo": [{"bar": "baz", "waldo": "fred"}], "foobar": 2}`,
49 | `{"hello": {"world": 1, "missing": "key"}, "foo": [{"bar": "baz"}]}`))
50 | }
51 |
52 | func TestJSONContains_HashAndArrayNotEquivalent(t *testing.T) {
53 | mockT := new(testing.T)
54 | assert.False(t, JSONContains(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`))
55 | }
56 |
57 | func TestJSONContains_ActualIsNotJSON(t *testing.T) {
58 | mockT := new(testing.T)
59 | assert.False(t, JSONContains(mockT, `{"foo": "bar"}`, "Not JSON"))
60 | }
61 |
62 | func TestJSONContains_ExpectedIsNotJSON(t *testing.T) {
63 | mockT := new(testing.T)
64 | assert.False(t, JSONContains(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`))
65 | }
66 |
67 | func TestJSONContains_ExpectedAndActualNotJSON(t *testing.T) {
68 | mockT := new(testing.T)
69 | assert.False(t, JSONContains(mockT, "Not JSON", "Not JSON"))
70 | }
71 |
72 | func TestJSONContains_ArraysOfDifferentOrder(t *testing.T) {
73 | mockT := new(testing.T)
74 | assert.False(t, JSONContains(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`))
75 | }
76 |
--------------------------------------------------------------------------------
/pkg/framework/core/common/errors_handling.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "github.com/ozontech/allure-go/pkg/allure"
5 | "github.com/ozontech/allure-go/pkg/framework/core/constants"
6 | )
7 |
8 | type ErrorT interface {
9 | Errorf(format string, args ...interface{})
10 | Logf(format string, args ...interface{})
11 | FailNow()
12 | }
13 |
14 | type ErrorProvider interface {
15 | StopResult(status allure.Status)
16 | UpdateResultStatus(msg string, trace string)
17 | }
18 |
19 | func TestError(t ErrorT, provider ErrorProvider, contextName, errMsg string) {
20 | short := errMsg
21 | if len(errMsg) > 100 {
22 | // TODO: trim properly to avoid invalid UTF-8
23 | short = errMsg[:100]
24 | }
25 |
26 | switch contextName {
27 | case constants.TestContextName, constants.BeforeEachContextName:
28 | provider.StopResult(allure.Broken)
29 | provider.UpdateResultStatus(short, errMsg)
30 | t.Errorf(errMsg)
31 | t.FailNow()
32 |
33 | case constants.AfterEachContextName, constants.AfterAllContextName:
34 | t.Logf(errMsg)
35 | provider.UpdateResultStatus(short, errMsg)
36 |
37 | case constants.BeforeAllContextName:
38 | t.Logf(errMsg)
39 | provider.UpdateResultStatus(short, errMsg)
40 | t.FailNow()
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/pkg/framework/core/common/errors_handling_test.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "github.com/ozontech/allure-go/pkg/allure"
5 | "github.com/ozontech/allure-go/pkg/framework/core/constants"
6 | "github.com/stretchr/testify/require"
7 | "testing"
8 | )
9 |
10 | type errorTMock struct {
11 | logF bool
12 | errorF bool
13 | failNow bool
14 | }
15 |
16 | func (e *errorTMock) Errorf(format string, args ...interface{}) {
17 | e.errorF = true
18 | }
19 |
20 | func (e *errorTMock) Logf(format string, args ...interface{}) {
21 | e.logF = true
22 | }
23 |
24 | func (e *errorTMock) FailNow() {
25 | e.failNow = true
26 | }
27 |
28 | type errorProviderMock struct {
29 | status allure.Status
30 | msg string
31 | trace string
32 | }
33 |
34 | func (m *errorProviderMock) StopResult(status allure.Status) {
35 | m.status = status
36 | }
37 |
38 | func (m *errorProviderMock) UpdateResultStatus(msg string, trace string) {
39 | m.msg = msg
40 | m.trace = trace
41 | }
42 |
43 | func TestTestError_less100(t *testing.T) {
44 | errTMock := &errorTMock{}
45 | errProviderMock := &errorProviderMock{}
46 |
47 | TestError(errTMock, errProviderMock, constants.TestContextName, "errMsg")
48 | require.Equal(t, "errMsg", errProviderMock.msg)
49 | require.Equal(t, "errMsg", errProviderMock.trace)
50 | require.Equal(t, allure.Broken, errProviderMock.status)
51 | require.True(t, errTMock.errorF)
52 | require.True(t, errTMock.failNow)
53 |
54 | errTMock = &errorTMock{}
55 | errProviderMock = &errorProviderMock{}
56 |
57 | TestError(errTMock, errProviderMock, constants.BeforeEachContextName, "errMsg")
58 | require.Equal(t, "errMsg", errProviderMock.msg)
59 | require.Equal(t, "errMsg", errProviderMock.trace)
60 | require.Equal(t, allure.Broken, errProviderMock.status)
61 | require.True(t, errTMock.errorF)
62 | require.True(t, errTMock.failNow)
63 |
64 | errTMock = &errorTMock{}
65 | errProviderMock = &errorProviderMock{}
66 |
67 | TestError(errTMock, errProviderMock, constants.BeforeAllContextName, "errMsg")
68 | require.Equal(t, "errMsg", errProviderMock.msg)
69 | require.Equal(t, "errMsg", errProviderMock.trace)
70 | require.Empty(t, errProviderMock.status)
71 | require.True(t, errTMock.logF)
72 | require.True(t, errTMock.failNow)
73 |
74 | errTMock = &errorTMock{}
75 | errProviderMock = &errorProviderMock{}
76 |
77 | TestError(errTMock, errProviderMock, constants.AfterEachContextName, "errMsg")
78 | require.Equal(t, "errMsg", errProviderMock.msg)
79 | require.Equal(t, "errMsg", errProviderMock.trace)
80 | require.Empty(t, errProviderMock.status)
81 | require.True(t, errTMock.logF)
82 |
83 | errTMock = &errorTMock{}
84 | errProviderMock = &errorProviderMock{}
85 |
86 | TestError(errTMock, errProviderMock, constants.AfterAllContextName, "errMsg")
87 | require.Equal(t, "errMsg", errProviderMock.msg)
88 | require.Equal(t, "errMsg", errProviderMock.trace)
89 | require.Empty(t, errProviderMock.status)
90 | require.True(t, errTMock.logF)
91 | }
92 |
93 | func TestTestError_more100(t *testing.T) {
94 | errTMock := &errorTMock{}
95 | errProviderMock := &errorProviderMock{}
96 | errMsg := `errMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMserrMs`
97 | TestError(errTMock, errProviderMock, constants.TestContextName, errMsg)
98 | require.Equal(t, errMsg[:100], errProviderMock.msg)
99 | require.Equal(t, errMsg, errProviderMock.trace)
100 | require.Equal(t, allure.Broken, errProviderMock.status)
101 | require.True(t, errTMock.errorF)
102 | require.True(t, errTMock.failNow)
103 |
104 | errTMock = &errorTMock{}
105 | errProviderMock = &errorProviderMock{}
106 | TestError(errTMock, errProviderMock, constants.BeforeAllContextName, errMsg)
107 | require.Equal(t, errMsg[:100], errProviderMock.msg)
108 | require.Equal(t, errMsg, errProviderMock.trace)
109 | require.Empty(t, errProviderMock.status)
110 | require.True(t, errTMock.logF)
111 | require.True(t, errTMock.failNow)
112 |
113 | errTMock = &errorTMock{}
114 | errProviderMock = &errorProviderMock{}
115 | TestError(errTMock, errProviderMock, constants.BeforeEachContextName, errMsg)
116 | require.Equal(t, errMsg[:100], errProviderMock.msg)
117 | require.Equal(t, errMsg, errProviderMock.trace)
118 | require.Equal(t, allure.Broken, errProviderMock.status)
119 | require.True(t, errTMock.errorF)
120 | require.True(t, errTMock.failNow)
121 |
122 | errTMock = &errorTMock{}
123 | errProviderMock = &errorProviderMock{}
124 | TestError(errTMock, errProviderMock, constants.AfterEachContextName, errMsg)
125 | require.Equal(t, errMsg[:100], errProviderMock.msg)
126 | require.Equal(t, errMsg, errProviderMock.trace)
127 | require.Empty(t, errProviderMock.status)
128 | require.True(t, errTMock.logF)
129 |
130 | errTMock = &errorTMock{}
131 | errProviderMock = &errorProviderMock{}
132 | TestError(errTMock, errProviderMock, constants.AfterAllContextName, errMsg)
133 | require.Equal(t, errMsg[:100], errProviderMock.msg)
134 | require.Equal(t, errMsg, errProviderMock.trace)
135 | require.Empty(t, errProviderMock.status)
136 | require.True(t, errTMock.logF)
137 | }
138 |
--------------------------------------------------------------------------------
/pkg/framework/core/common/hooks.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "fmt"
5 | "runtime/debug"
6 | "testing"
7 |
8 | "github.com/ozontech/allure-go/pkg/framework/provider"
9 | )
10 |
11 | type HookFunc func(t InternalT, provider HookProvider) (bool, error)
12 |
13 | type HookType string
14 |
15 | // HookType constants
16 | const (
17 | BeforeAll HookType = "BeforeAll"
18 | AfterAll HookType = "AfterAll"
19 | BeforeEach HookType = "BeforeEach"
20 | AfterEach HookType = "AfterEach"
21 | )
22 |
23 | func (h HookType) String() string {
24 | return string(h)
25 | }
26 |
27 | func CarriedHook(hook HookType, getHookBody func() func(t provider.T)) HookFunc {
28 | return func(t InternalT, provider HookProvider) (result bool, err error) {
29 | result = true
30 | if hookBody := getHookBody(); hookBody != nil {
31 | t.WG().Add(1)
32 | defer t.WG().Wait()
33 |
34 | // for correct logs
35 | oldT := t.RealT()
36 | defer t.SetRealT(oldT)
37 |
38 | // HACK: allows testing library control routines to avoid deadlocks and appropriate waiting
39 | result = t.RealT().Run(string(hook), func(realT *testing.T) {
40 | defer t.WG().Done()
41 | switch hook {
42 | case BeforeAll:
43 | provider.BeforeAllContext()
44 |
45 | case AfterAll:
46 | provider.AfterAllContext()
47 |
48 | case BeforeEach:
49 | provider.BeforeEachContext()
50 |
51 | case AfterEach:
52 | provider.AfterEachContext()
53 | }
54 |
55 | defer func() {
56 | r := recover()
57 | if r != nil {
58 | err = fmt.Errorf("%s hook panicked:%v\n%s", hook, r, debug.Stack())
59 | t.Errorf("%s hook panicked:%v\n%s", hook, r, debug.Stack())
60 | t.FailNow()
61 | }
62 | }()
63 |
64 | t.SetRealT(realT)
65 | hookBody(t)
66 | })
67 | }
68 | return
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/pkg/framework/core/common/interfaces.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "sync"
5 |
6 | "github.com/ozontech/allure-go/pkg/allure"
7 | "github.com/ozontech/allure-go/pkg/framework/provider"
8 | )
9 |
10 | type ParentT interface {
11 | GetProvider() provider.Provider
12 | GetResult() *allure.Result
13 | }
14 |
15 | type HookProvider interface {
16 | BeforeEachContext()
17 | AfterEachContext()
18 | BeforeAllContext()
19 | AfterAllContext()
20 |
21 | GetSuiteMeta() provider.SuiteMeta
22 | GetTestMeta() provider.TestMeta
23 | }
24 |
25 | type InternalT interface {
26 | provider.T
27 |
28 | SetRealT(realT provider.TestingT)
29 | WG() *sync.WaitGroup
30 | }
31 |
--------------------------------------------------------------------------------
/pkg/framework/core/common/steps.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "fmt"
5 | "runtime/debug"
6 |
7 | "github.com/ozontech/allure-go/pkg/allure"
8 | "github.com/ozontech/allure-go/pkg/framework/provider"
9 | )
10 |
11 | // WithNewStep opens nesting for struct.Step
12 | // Any other struct.Step that will be added to struct.AllureResult object will be added as child step
13 | func (c *Common) WithNewStep(stepName string, step func(ctx provider.StepCtx), params ...*allure.Parameter) {
14 | stCtx := NewStepCtx(c, c.Provider, stepName, params...)
15 | defer c.Step(stCtx.CurrentStep())
16 | defer func() {
17 | r := recover()
18 | stCtx.WG().Wait()
19 | stCtx.CurrentStep().Finish()
20 | if r != nil {
21 | ctxName := c.ExecutionContext().GetName()
22 | errMsg := fmt.Sprintf("%s panicked: %v\n%s", ctxName, r, debug.Stack())
23 | stCtx.Broken()
24 | TestError(c.TestingT, c.Provider, c.Provider.ExecutionContext().GetName(), errMsg)
25 | }
26 | }()
27 | step(stCtx)
28 | }
29 |
30 | // WithNewAsyncStep opens nesting for struct.Step
31 | // Any other struct.Step that will be added to struct.AllureResult object will be added as child step
32 | func (c *Common) WithNewAsyncStep(stepName string, step func(ctx provider.StepCtx), params ...*allure.Parameter) {
33 | c.wg.Add(1)
34 | go func() {
35 | defer c.wg.Done()
36 | c.WithNewStep(stepName, step, params...)
37 | }()
38 | }
39 |
--------------------------------------------------------------------------------
/pkg/framework/core/common/tempdir.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "strings"
7 | "unicode"
8 | "unicode/utf8"
9 | )
10 |
11 | func (c *Common) TempDir() string {
12 | // HACK: Temp solution for the go stdlib bug.
13 | //
14 | // Copied from https://github.com/golang/go/blob/master/src/testing/testing.go#L1307
15 | //
16 | // testing.T.TempDir() will fail if test name is too long.
17 | //
18 | // See this issue https://github.com/golang/go/issues/71742
19 | //
20 | // It was fixed recently (as of 14.05.2025) by the go team https://go.dev/cl/671577
21 | // but it will require some time until it reaches the stable version.
22 |
23 | // Use a single parent directory for all the temporary directories
24 | // created by a test, each numbered sequentially.
25 | c.tempDirMu.Lock()
26 |
27 | var nonExistent bool
28 |
29 | if c.tempDir == "" { // Usually the case with js/wasm
30 | nonExistent = true
31 | } else {
32 | _, err := os.Stat(c.tempDir)
33 | nonExistent = os.IsNotExist(err)
34 |
35 | if err != nil && !nonExistent {
36 | c.Fatalf("TempDir: %v", err)
37 | }
38 | }
39 |
40 | if nonExistent {
41 | c.Helper()
42 | pattern := c.Name()
43 |
44 | // Limit length of file names on disk.
45 | // Invalid runes from slicing are dropped by strings.Map below.
46 | if len(pattern) > 64 {
47 | pattern = pattern[:64]
48 | }
49 |
50 | // Drop unusual characters (such as path separators or
51 | // characters interacting with globs) from the directory name to
52 | // avoid surprising os.MkdirTemp behavior.
53 | mapper := func(r rune) rune {
54 | if r < utf8.RuneSelf {
55 | const allowed = "!#$%&()+,-.=@^_{}~ "
56 |
57 | if '0' <= r && r <= '9' ||
58 | 'a' <= r && r <= 'z' ||
59 | 'A' <= r && r <= 'Z' {
60 | return r
61 | }
62 |
63 | if strings.ContainsRune(allowed, r) {
64 | return r
65 | }
66 | } else if unicode.IsLetter(r) || unicode.IsNumber(r) {
67 | return r
68 | }
69 |
70 | return -1
71 | }
72 |
73 | pattern = strings.Map(mapper, pattern)
74 | c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern)
75 |
76 | if c.tempDirErr == nil {
77 | c.Cleanup(func() {
78 | if err := os.RemoveAll(c.tempDir); err != nil {
79 | c.Errorf("TempDir RemoveAll cleanup: %v", err)
80 | }
81 | })
82 | }
83 | }
84 |
85 | if c.tempDirErr == nil {
86 | c.tempDirSeq++
87 | }
88 |
89 | seq := c.tempDirSeq
90 |
91 | c.tempDirMu.Unlock()
92 |
93 | if c.tempDirErr != nil {
94 | c.Fatalf("TempDir: %v", c.tempDirErr)
95 | }
96 |
97 | dir := fmt.Sprintf("%s%c%03d", c.tempDir, os.PathSeparator, seq)
98 |
99 | //nolint:gosec // copied from the stdlib
100 | if err := os.Mkdir(dir, 0o777); err != nil {
101 | c.Fatalf("TempDir: %v", err)
102 | }
103 |
104 | return dir
105 | }
106 |
--------------------------------------------------------------------------------
/pkg/framework/core/constants/constants.go:
--------------------------------------------------------------------------------
1 | package constants
2 |
3 | // Context names constants
4 | const (
5 | TestContextName = "test"
6 | BeforeEachContextName = "beforeEach"
7 | AfterEachContextName = "afterEach"
8 | BeforeAllContextName = "beforeAll"
9 | AfterAllContextName = "afterAll"
10 | )
11 |
--------------------------------------------------------------------------------
/pkg/framework/core/constants/constants_test.go:
--------------------------------------------------------------------------------
1 | package constants
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/require"
7 | )
8 |
9 | func TestConstants(t *testing.T) {
10 | require.Equal(t, "test", TestContextName)
11 | require.Equal(t, "beforeEach", BeforeEachContextName)
12 | require.Equal(t, "afterEach", AfterEachContextName)
13 | require.Equal(t, "beforeAll", BeforeAllContextName)
14 | require.Equal(t, "afterAll", AfterAllContextName)
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/framework/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/ozontech/allure-go/pkg/framework
2 |
3 | go 1.17
4 |
5 | replace github.com/ozontech/allure-go/pkg/allure => ../allure
6 |
7 | require (
8 | github.com/ozontech/allure-go/pkg/allure v0.6.14
9 | github.com/pkg/errors v0.9.1
10 | github.com/stretchr/testify v1.7.1
11 | )
12 |
13 | require (
14 | github.com/davecgh/go-spew v1.1.1 // indirect
15 | github.com/google/uuid v1.3.0 // indirect
16 | github.com/pmezard/go-difflib v1.0.0 // indirect
17 | gopkg.in/yaml.v3 v3.0.0 // indirect
18 | )
19 |
--------------------------------------------------------------------------------
/pkg/framework/go.sum:
--------------------------------------------------------------------------------
1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
5 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
6 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
7 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
8 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
9 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
10 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
11 | github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
12 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
13 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
14 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
15 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
16 | gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
17 | gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
18 |
--------------------------------------------------------------------------------
/pkg/framework/provider/allure.go:
--------------------------------------------------------------------------------
1 | package provider
2 |
3 | import (
4 | "github.com/ozontech/allure-go/pkg/allure"
5 | )
6 |
7 | type SystemLabels interface {
8 | Package(value string)
9 | FrameWork(value string)
10 | Host(value string)
11 | Thread(value string)
12 | Language(value string)
13 | }
14 |
15 | type SuiteLabels interface {
16 | AddSuiteLabel(value string)
17 | AddSubSuite(value string)
18 | AddParentSuite(value string)
19 | }
20 |
21 | type DescriptionLabels interface {
22 | ID(value string)
23 | AllureID(value string)
24 | Epic(value string)
25 | Layer(value string)
26 | Feature(value string)
27 | Story(value string)
28 | Severity(severityType allure.SeverityType)
29 | Tag(value string)
30 | Tags(values ...string)
31 | Owner(value string)
32 | Lead(value string)
33 | Label(label *allure.Label)
34 | Labels(labels ...*allure.Label)
35 | ReplaceLabel(label *allure.Label)
36 | }
37 |
38 | type Links interface {
39 | SetIssue(issue string)
40 | SetTestCase(testCase string)
41 | Link(link *allure.Link)
42 | TmsLink(tmsCase string)
43 | TmsLinks(tmsCases ...string)
44 | }
45 |
46 | type DescriptionFields interface {
47 | Title(args ...interface{})
48 | Titlef(format string, args ...interface{})
49 | Description(args ...interface{})
50 | Descriptionf(format string, args ...interface{})
51 | Stage(args ...interface{})
52 | Stagef(format string, args ...interface{})
53 | }
54 |
55 | type AllureSteps interface {
56 | Step(step *allure.Step)
57 | NewStep(stepName string, params ...*allure.Parameter)
58 | }
59 |
60 | type Attachments interface {
61 | WithAttachments(attachment ...*allure.Attachment)
62 | WithNewAttachment(name string, mimeType allure.MimeType, content []byte)
63 | }
64 |
65 | type Parameters interface {
66 | WithParameters(params ...*allure.Parameter)
67 | WithNewParameters(kv ...interface{})
68 | }
69 |
70 | type AllureForward interface {
71 | DescriptionLabels
72 | SuiteLabels
73 | Links
74 | DescriptionFields
75 | AllureSteps
76 | Attachments
77 | Parameters
78 | }
79 |
80 | type AllureForwardFull interface {
81 | AllureForward
82 | SystemLabels
83 | }
84 |
--------------------------------------------------------------------------------
/pkg/framework/provider/provider.go:
--------------------------------------------------------------------------------
1 | package provider
2 |
3 | import (
4 | "github.com/ozontech/allure-go/pkg/allure"
5 | )
6 |
7 | type Provider interface {
8 | AllureForwardFull
9 |
10 | GetResult() *allure.Result
11 | UpdateResultStatus(msg string, trace string)
12 | StopResult(status allure.Status)
13 |
14 | SetTestMeta(meta TestMeta)
15 | GetTestMeta() TestMeta
16 | GetSuiteMeta() SuiteMeta
17 | ExecutionContext() ExecutionContext
18 |
19 | TestContext()
20 | BeforeEachContext()
21 | AfterEachContext()
22 | BeforeAllContext()
23 | AfterAllContext()
24 |
25 | NewTest(testName, packageName string, tags ...string)
26 | FinishTest() error
27 | }
28 |
29 | type TestMeta interface {
30 | GetResult() *allure.Result
31 | SetResult(result *allure.Result)
32 |
33 | GetContainer() *allure.Container
34 |
35 | SetBeforeEach(hook func(T))
36 | GetBeforeEach() func(T)
37 | SetAfterEach(hook func(T))
38 | GetAfterEach() func(T)
39 | }
40 |
41 | type SuiteMeta interface {
42 | GetPackageName() string
43 | GetRunner() string
44 | GetSuiteName() string
45 | GetParentSuite() string
46 | GetSuiteFullName() string
47 | GetContainer() *allure.Container
48 |
49 | SetBeforeAll(func(T))
50 | SetAfterAll(func(T))
51 | GetBeforeAll() func(T)
52 | GetAfterAll() func(T)
53 | }
54 |
55 | type ExecutionContext interface {
56 | AddStep(step *allure.Step)
57 | AddAttachments(attachment ...*allure.Attachment)
58 | GetName() string
59 | }
60 |
--------------------------------------------------------------------------------
/pkg/framework/provider/test.go:
--------------------------------------------------------------------------------
1 | package provider
2 |
3 | import (
4 | "testing"
5 | "time"
6 |
7 | "github.com/ozontech/allure-go/pkg/allure"
8 | "github.com/stretchr/testify/assert"
9 | )
10 |
11 | type TestingT interface {
12 | testing.TB
13 |
14 | Parallel()
15 | Run(testName string, testBody func(t *testing.T)) bool
16 | }
17 |
18 | type T interface {
19 | testing.TB
20 |
21 | AllureForward
22 |
23 | Parallel()
24 |
25 | RealT() TestingT
26 | XSkip()
27 | Break(args ...interface{})
28 | Breakf(format string, args ...interface{})
29 | Broken()
30 | BrokenNow()
31 | SkipOnPrint()
32 | Assert() Asserts
33 | Require() Asserts
34 | Run(testName string, testBody func(T), tags ...string) *allure.Result
35 |
36 | LogStep(args ...interface{})
37 | LogfStep(format string, args ...interface{})
38 | WithNewStep(stepName string, step func(sCtx StepCtx), params ...*allure.Parameter)
39 | WithNewAsyncStep(stepName string, step func(sCtx StepCtx), params ...*allure.Parameter)
40 | WithTestSetup(setup func(T))
41 | WithTestTeardown(teardown func(T))
42 | }
43 |
44 | type StepCtx interface {
45 | Step(step *allure.Step)
46 | NewStep(stepName string, parameters ...*allure.Parameter)
47 | WithNewStep(stepName string, step func(sCtx StepCtx), params ...*allure.Parameter)
48 | WithNewAsyncStep(stepName string, step func(sCtx StepCtx), params ...*allure.Parameter)
49 |
50 | WithParameters(parameters ...*allure.Parameter)
51 | WithNewParameters(kv ...interface{})
52 |
53 | WithAttachments(attachment ...*allure.Attachment)
54 | WithNewAttachment(name string, mimeType allure.MimeType, content []byte)
55 |
56 | Assert() Asserts
57 | Require() Asserts
58 |
59 | LogStep(args ...interface{})
60 | LogfStep(format string, args ...interface{})
61 | WithStatusDetails(message, trace string)
62 | CurrentStep() *allure.Step
63 |
64 | Broken()
65 | BrokenNow()
66 |
67 | Fail()
68 | FailNow()
69 | Log(args ...interface{})
70 | Logf(format string, args ...interface{})
71 | Error(args ...interface{})
72 | Errorf(format string, args ...interface{})
73 | Break(args ...interface{})
74 | Breakf(format string, args ...interface{})
75 | Name() string
76 | }
77 |
78 | // Asserts ...
79 | type Asserts interface {
80 | Exactly(expected, actual interface{}, msgAndArgs ...interface{})
81 | Same(expected, actual interface{}, msgAndArgs ...interface{})
82 | NotSame(expected, actual interface{}, msgAndArgs ...interface{})
83 | Equal(expected, actual interface{}, msgAndArgs ...interface{})
84 | NotEqual(expected, actual interface{}, msgAndArgs ...interface{})
85 | EqualValues(expected, actual interface{}, msgAndArgs ...interface{})
86 | NotEqualValues(expected, actual interface{}, msgAndArgs ...interface{})
87 | Error(err error, msgAndArgs ...interface{})
88 | NoError(err error, msgAndArgs ...interface{})
89 | EqualError(theError error, errString string, msgAndArgs ...interface{})
90 | ErrorIs(err, target error, msgAndArgs ...interface{})
91 | ErrorAs(err error, target interface{}, msgAndArgs ...interface{})
92 | NotNil(object interface{}, msgAndArgs ...interface{})
93 | Nil(object interface{}, msgAndArgs ...interface{})
94 | Len(object interface{}, length int, msgAndArgs ...interface{})
95 | NotContains(s, contains interface{}, msgAndArgs ...interface{})
96 | Contains(s, contains interface{}, msgAndArgs ...interface{})
97 | Greater(e1, e2 interface{}, msgAndArgs ...interface{})
98 | GreaterOrEqual(e1, e2 interface{}, msgAndArgs ...interface{})
99 | Less(e1, e2 interface{}, msgAndArgs ...interface{})
100 | LessOrEqual(e1, e2 interface{}, msgAndArgs ...interface{})
101 | Implements(interfaceObject, object interface{}, msgAndArgs ...interface{})
102 | Empty(object interface{}, msgAndArgs ...interface{})
103 | NotEmpty(object interface{}, msgAndArgs ...interface{})
104 | WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{})
105 | JSONEq(expected, actual string, msgAndArgs ...interface{})
106 | JSONContains(expected, actual string, msgAndArgs ...interface{})
107 | Subset(list, subset interface{}, msgAndArgs ...interface{})
108 | NotSubset(list, subset interface{}, msgAndArgs ...interface{})
109 | IsType(expectedType, object interface{}, msgAndArgs ...interface{})
110 | True(value bool, msgAndArgs ...interface{})
111 | False(value bool, msgAndArgs ...interface{})
112 | Regexp(rx, str interface{}, msgAndArgs ...interface{})
113 | ElementsMatch(listA, listB interface{}, msgAndArgs ...interface{})
114 | DirExists(path string, msgAndArgs ...interface{})
115 | Condition(condition assert.Comparison, msgAndArgs ...interface{})
116 | Zero(i interface{}, msgAndArgs ...interface{})
117 | NotZero(i interface{}, msgAndArgs ...interface{})
118 | InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{})
119 | Eventually(condition func() bool, waitFor, tick time.Duration, msgAndArgs ...interface{})
120 | }
121 |
--------------------------------------------------------------------------------
/pkg/framework/runner/contants.go:
--------------------------------------------------------------------------------
1 | package runner
2 |
3 | const (
4 | tableParamPrefix = "Param"
5 | tableTestPrefix = "TableTest"
6 | testPrefix = "Test"
7 | )
8 |
9 | // magic number of depth caller to find test's caller package
10 | const defaultPackageDepth = 2
11 |
--------------------------------------------------------------------------------
/pkg/framework/runner/interfaces.go:
--------------------------------------------------------------------------------
1 | package runner
2 |
3 | import (
4 | "sync"
5 | "testing"
6 |
7 | "github.com/ozontech/allure-go/pkg/allure"
8 | "github.com/ozontech/allure-go/pkg/framework/provider"
9 | )
10 |
11 | // AllureBeforeTest has a BeforeEach method, which will run before each
12 | // test in the suite.
13 | type AllureBeforeTest interface {
14 | BeforeEach(t provider.T)
15 | }
16 |
17 | // AllureAfterTest has a AfterEach method, which will run after
18 | // each test in the suite.
19 | type AllureAfterTest interface {
20 | AfterEach(t provider.T)
21 | }
22 |
23 | // AllureBeforeSuite has a BeforeAll method, which will run before the
24 | // tests in the suite are run.
25 | type AllureBeforeSuite interface {
26 | BeforeAll(t provider.T)
27 | }
28 |
29 | // AllureAfterSuite has a AfterAll method, which will run after
30 | // all the tests in the suite have been run.
31 | type AllureAfterSuite interface {
32 | AfterAll(t provider.T)
33 | }
34 |
35 | // AllureIDSuite has a GetAllureID method,
36 | // which will produce allureIDs for the test by its name
37 | type AllureIDSuite interface {
38 | GetAllureID(testName string) string
39 | }
40 |
41 | // ParametrizedSuite suit can initialize parameters for
42 | // parametrized test before running hooks
43 | type ParametrizedSuite interface {
44 | InitializeTestsParams()
45 | }
46 |
47 | // ParametrizedTestParam parameter for parametrized test
48 | // with custom AllureId and Title
49 | type ParametrizedTestParam interface {
50 | GetAllureID() string
51 | GetAllureTitle() string
52 | }
53 |
54 | type TestSuite interface {
55 | GetRunner() TestRunner
56 | SetRunner(runner TestRunner)
57 | }
58 |
59 | type TestingT interface {
60 | testing.TB
61 |
62 | Parallel()
63 | Run(testName string, testBody func(t *testing.T)) bool
64 | }
65 |
66 | type TestRunner interface {
67 | NewTest(testName string, testBody func(provider.T), tags ...string)
68 | BeforeEach(hookBody func(provider.T))
69 | AfterEach(hookBody func(provider.T))
70 | BeforeAll(hookBody func(provider.T))
71 | AfterAll(hookBody func(provider.T))
72 | RunTests() SuiteResult
73 | }
74 |
75 | type Test interface {
76 | GetBody() TestBody
77 | GetMeta() provider.TestMeta
78 | }
79 |
80 | type SuiteResult interface {
81 | NewResult(result TestResult)
82 | GetContainer() *allure.Container
83 | GetAllTestResults() []TestResult
84 | GetResultByName(name string) TestResult
85 | GetResultByUUID(uuid string) TestResult
86 | ToJSON() ([]byte, error)
87 | }
88 |
89 | type TestResult interface {
90 | GetResult() *allure.Result
91 | GetContainer() *allure.Container
92 | Print() error
93 | ToJSON() ([]byte, error)
94 | }
95 |
96 | type internalT interface {
97 | provider.T
98 |
99 | SetRealT(t provider.TestingT)
100 | GetProvider() provider.Provider
101 | WG() *sync.WaitGroup
102 | GetResult() *allure.Result
103 | }
104 |
--------------------------------------------------------------------------------
/pkg/framework/runner/tests.go:
--------------------------------------------------------------------------------
1 | package runner
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "reflect"
7 | "sync"
8 |
9 | "github.com/ozontech/allure-go/pkg/allure"
10 | "github.com/ozontech/allure-go/pkg/framework/provider"
11 | )
12 |
13 | type suiteResult struct {
14 | Container *allure.Container `json:"container,omitempty"`
15 | TestResults []TestResult `json:"test_results,omitempty"`
16 |
17 | mu sync.Mutex
18 | }
19 |
20 | // NewSuiteResult Returns new SuiteResult
21 | func NewSuiteResult(container *allure.Container) SuiteResult {
22 | return &suiteResult{Container: container}
23 | }
24 |
25 | // NewResult appends test result to suite result
26 | func (sr *suiteResult) NewResult(result TestResult) {
27 | sr.mu.Lock()
28 | defer sr.mu.Unlock()
29 |
30 | sr.TestResults = append(sr.TestResults, result)
31 | }
32 |
33 | // GetContainer returns parent Container
34 | func (sr *suiteResult) GetContainer() *allure.Container {
35 | return sr.Container
36 | }
37 |
38 | // GetAllTestResults returns all test results of suite
39 | func (sr *suiteResult) GetAllTestResults() []TestResult {
40 | return sr.TestResults
41 | }
42 |
43 | // GetResultByName searches result by name and returns it
44 | func (sr *suiteResult) GetResultByName(name string) TestResult {
45 | for _, tr := range sr.TestResults {
46 | if r := tr.GetResult(); r != nil {
47 | if r.Name == name {
48 | return tr
49 | }
50 | }
51 | }
52 |
53 | return nil
54 | }
55 |
56 | // GetResultByUUID searches result by UUID and returns it
57 | func (sr *suiteResult) GetResultByUUID(uuid string) TestResult {
58 | for _, tr := range sr.TestResults {
59 | if r := tr.GetResult(); r != nil {
60 | if r.UUID.String() == uuid {
61 | return tr
62 | }
63 | }
64 | }
65 | return nil
66 | }
67 |
68 | // ToJSON marshall result to Json object
69 | //
70 | // Deprecated: use [json.Marshal] instead.
71 | func (sr *suiteResult) ToJSON() ([]byte, error) {
72 | return json.Marshal(sr)
73 | }
74 |
75 | type testResult struct {
76 | Result *allure.Result `json:"result,omitempty"`
77 | Container *allure.Container `json:"container,omitempty"`
78 | }
79 |
80 | // NewTestResult returns new test result
81 | func NewTestResult(result *allure.Result, container *allure.Container) TestResult {
82 | return &testResult{
83 | Result: result,
84 | Container: container,
85 | }
86 | }
87 |
88 | // GetResult returns result
89 | func (tr *testResult) GetResult() *allure.Result {
90 | return tr.Result
91 | }
92 |
93 | // GetContainer returns Container
94 | func (tr *testResult) GetContainer() *allure.Container {
95 | return tr.Container
96 | }
97 |
98 | // Print returns print
99 | func (tr *testResult) Print() error {
100 | var (
101 | resultErr error
102 | containerErr error
103 | )
104 |
105 | result := tr.GetResult()
106 |
107 | if result != nil {
108 | resultErr = result.Done()
109 | } else {
110 | resultErr = fmt.Errorf("failed to print Result. Reason: *allure.Result is nil")
111 | }
112 |
113 | container := tr.GetContainer()
114 | if container != nil {
115 | containerErr = container.Done()
116 | } else {
117 | containerErr = fmt.Errorf("failed to print Container. Reason: *allure.Container is nil")
118 | }
119 |
120 | if resultErr != nil && containerErr != nil {
121 | return fmt.Errorf("failed to print Result. Reason: %s\nAlso failed to print Container. Reason: %s", resultErr, containerErr)
122 | }
123 |
124 | if resultErr != nil {
125 | return resultErr
126 | }
127 |
128 | if containerErr != nil {
129 | return containerErr
130 | }
131 |
132 | return nil
133 | }
134 |
135 | // ToJSON marshall TestResult to the JSON
136 | //
137 | // Deprecated: use [json.Marshal] instead
138 | func (tr *testResult) ToJSON() ([]byte, error) {
139 | return json.Marshal(tr)
140 | }
141 |
142 | type TestBody func(t provider.T)
143 |
144 | type testMethod struct {
145 | testMeta provider.TestMeta
146 | testBody reflect.Method
147 | callArgs []reflect.Value
148 | }
149 |
150 | // GetArgs returns call args of the test
151 | func (t *testMethod) GetArgs() []reflect.Value {
152 | return t.callArgs
153 | }
154 |
155 | // GetRawBody returns reflect.Method of the test
156 | func (t *testMethod) GetRawBody() reflect.Method {
157 | return t.testBody
158 | }
159 |
160 | // GetBody returns wrapped function at the test
161 | func (t *testMethod) GetBody() TestBody {
162 | return func(pT provider.T) {
163 | t.testBody.Func.Call(insert(t.callArgs, 1, reflect.ValueOf(pT)))
164 | }
165 | }
166 |
167 | // GetMeta returns provider.TestMeta of the test
168 | func (t *testMethod) GetMeta() provider.TestMeta {
169 | return t.testMeta
170 | }
171 |
172 | type testFunc struct {
173 | testBody TestBody
174 | testMeta provider.TestMeta
175 | }
176 |
177 | // GetBody returns test function
178 | func (t *testFunc) GetBody() TestBody {
179 | return t.testBody
180 | }
181 |
182 | // GetMeta returns provider.TestMeta of the test
183 | func (t *testFunc) GetMeta() provider.TestMeta {
184 | return t.testMeta
185 | }
186 |
187 | func newTestFunc(body TestBody, testMeta provider.TestMeta) *testFunc {
188 | return &testFunc{
189 | testBody: body,
190 | testMeta: testMeta,
191 | }
192 | }
193 |
194 | func insert(a []reflect.Value, index int, value reflect.Value) []reflect.Value {
195 | if len(a) == index { // nil or empty slice or after last element
196 | return append(a, value)
197 | }
198 |
199 | a = append(a[:index+1], a[index:]...) // index < len(a)
200 | a[index] = value
201 |
202 | return a
203 | }
204 |
--------------------------------------------------------------------------------
/pkg/framework/suite/suite.go:
--------------------------------------------------------------------------------
1 | package suite
2 |
3 | import (
4 | "reflect"
5 | "runtime"
6 | "strings"
7 |
8 | "github.com/ozontech/allure-go/pkg/framework/provider"
9 | "github.com/ozontech/allure-go/pkg/framework/runner"
10 | )
11 |
12 | type Suite struct {
13 | runner runner.TestRunner
14 | }
15 |
16 | func (s *Suite) GetRunner() runner.TestRunner {
17 | return s.runner
18 | }
19 |
20 | func (s *Suite) SetRunner(runner runner.TestRunner) {
21 | s.runner = runner
22 | }
23 |
24 | func (s *Suite) RunSuite(t provider.T, suite runner.TestSuite) runner.SuiteResult {
25 | t.SkipOnPrint()
26 | parts := strings.Split(t.RealT().Name(), "/")
27 | parentName := parts[len(parts)-3]
28 |
29 | return runner.NewSuiteRunnerWithParent(t.RealT(), getPackage(2), cleanName(getSuiteName(suite)), parentName, suite).RunTests()
30 | }
31 |
32 | func (s *Suite) RunNamedSuite(t provider.T, suiteName string, suite runner.TestSuite) runner.SuiteResult {
33 | t.SkipOnPrint()
34 | parts := strings.Split(t.RealT().Name(), "/")
35 | parentName := parts[len(parts)-3]
36 |
37 | return runner.NewSuiteRunnerWithParent(t.RealT(), getPackage(2), suiteName, parentName, suite).RunTests()
38 | }
39 |
40 | func RunSuite(t provider.TestingT, suite runner.TestSuite) runner.SuiteResult {
41 | return runner.NewSuiteRunner(t, getPackage(2), getSuiteName(suite), suite).RunTests()
42 | }
43 |
44 | func RunNamedSuite(t provider.TestingT, suiteName string, suite runner.TestSuite) runner.SuiteResult {
45 | return runner.NewSuiteRunner(t, getPackage(2), suiteName, suite).RunTests()
46 | }
47 |
48 | func getSuiteName(suite interface{}) string {
49 | s := reflect.TypeOf(suite)
50 | if s.Kind() == reflect.Ptr {
51 | return s.Elem().Name()
52 | }
53 |
54 | return s.Name()
55 | }
56 |
57 | func cleanName(fullName string) string {
58 | nameParts := strings.Split(fullName, "/")
59 |
60 | removeIDs := make([]int, 0, len(nameParts))
61 |
62 | for idx, namePart := range nameParts {
63 | if strings.HasSuffix(namePart, "_Tests") {
64 | removeIDs = append(removeIDs, idx)
65 | }
66 | }
67 |
68 | for _, idx := range removeIDs {
69 | nameParts = remove(nameParts, idx)
70 | }
71 |
72 | return strings.Join(nameParts, "/")
73 | }
74 |
75 | func remove(slice []string, s int) []string {
76 | return append(slice[:s], slice[s+1:]...)
77 | }
78 |
79 | func getPackage(depth int) string {
80 | pc, _, _, _ := runtime.Caller(depth)
81 | funcName := runtime.FuncForPC(pc).Name()
82 | lastSlash := strings.LastIndexByte(funcName, '/')
83 | if lastSlash < 0 {
84 | lastSlash = 0
85 | }
86 |
87 | lastDot := strings.LastIndexByte(funcName[lastSlash:], '.') + lastSlash
88 |
89 | return funcName[:lastDot]
90 | }
91 |
--------------------------------------------------------------------------------
/pkg/framework/suite/suite_runner_test.go:
--------------------------------------------------------------------------------
1 | package suite
2 |
3 | import (
4 | "os"
5 | "sync"
6 | "testing"
7 | "time"
8 |
9 | "github.com/ozontech/allure-go/pkg/framework/provider"
10 | "github.com/ozontech/allure-go/pkg/framework/runner"
11 | "github.com/stretchr/testify/require"
12 | )
13 |
14 | type suiteRunnerTMock struct {
15 | testing.TB
16 |
17 | t *testing.T
18 | failNow bool
19 | parallel bool
20 | }
21 |
22 | func (m *suiteRunnerTMock) Name() string {
23 | return "testSuite"
24 | }
25 |
26 | func (m *suiteRunnerTMock) Parallel() {
27 | m.parallel = true
28 | }
29 |
30 | func (m *suiteRunnerTMock) FailNow() {
31 | m.failNow = true
32 | }
33 |
34 | func (m *suiteRunnerTMock) Run(testName string, testBody func(t *testing.T)) bool {
35 | testBody(m.t)
36 | return true
37 | }
38 |
39 | type TestSuiteRunner struct {
40 | Suite
41 | testSome1 bool
42 | testSome2 bool
43 | }
44 |
45 | func (s *TestSuiteRunner) TestSome1(t provider.T) {
46 | s.testSome1 = true
47 | }
48 |
49 | func (s *TestSuiteRunner) TestSome2(t provider.T) {
50 | s.testSome2 = true
51 | }
52 |
53 | func TestSuiteRunner_RunTests(t *testing.T) {
54 | allureDir := "./allure-results"
55 | defer os.RemoveAll(allureDir)
56 |
57 | suite := new(TestSuiteRunner)
58 |
59 | r := runner.NewSuiteRunner(t, "packageName", "suiteName", suite)
60 | r.RunTests()
61 |
62 | require.True(t, suite.testSome1)
63 | require.True(t, suite.testSome2)
64 | }
65 |
66 | type TestSuiteRunnerPanic struct {
67 | Suite
68 | wg sync.WaitGroup
69 | testSome1 bool
70 | }
71 |
72 | func (s *TestSuiteRunnerPanic) TestSome1(t provider.T) {
73 | defer s.wg.Done()
74 | s.testSome1 = true
75 | panic("whoops")
76 | }
77 |
78 | func TestRunner_RunTests_panic(t *testing.T) {
79 | t.Skipf("This test need to be reworked")
80 | allureDir := "./allure-results"
81 | defer os.RemoveAll(allureDir)
82 |
83 | suite := new(TestSuiteRunnerPanic)
84 | suite.wg = sync.WaitGroup{}
85 | mockT := &suiteRunnerTMock{t: new(testing.T)}
86 | r := runner.NewSuiteRunner(mockT, "packageName", "suiteName", suite)
87 | suite.wg.Add(1)
88 | go require.NotPanics(t, func() {
89 | r.RunTests()
90 | })
91 | suite.wg.Wait()
92 | require.True(t, suite.testSome1)
93 | }
94 |
95 | type TestSuiteRunnerHooks struct {
96 | Suite
97 | wg sync.WaitGroup
98 | testSome1 bool
99 |
100 | beforeAll bool
101 | beforeEach bool
102 | afterEach bool
103 | afterAll bool
104 | }
105 |
106 | func (s *TestSuiteRunnerHooks) BeforeAll(t provider.T) {
107 | s.beforeAll = true
108 | }
109 |
110 | func (s *TestSuiteRunnerHooks) BeforeEach(t provider.T) {
111 | s.beforeEach = true
112 | }
113 |
114 | func (s *TestSuiteRunnerHooks) AfterEach(t provider.T) {
115 | s.afterEach = true
116 | }
117 |
118 | func (s *TestSuiteRunnerHooks) AfterAll(t provider.T) {
119 | s.afterAll = true
120 | }
121 |
122 | func (s *TestSuiteRunnerHooks) TestSome(t provider.T) {
123 | s.testSome1 = true
124 | }
125 |
126 | func TestRunner_hooks(t *testing.T) {
127 | t.Skipf("This test need to be reworked")
128 | allureDir := "./allure-results"
129 | defer os.RemoveAll(allureDir)
130 |
131 | suite := new(TestSuiteRunnerHooks)
132 | mockT := &suiteRunnerTMock{t: new(testing.T)}
133 | r := runner.NewSuiteRunner(mockT, "packageName", "suiteName", suite)
134 | r.RunTests()
135 |
136 | require.True(t, suite.beforeAll)
137 | require.True(t, suite.beforeEach)
138 | require.True(t, suite.afterEach)
139 | require.True(t, suite.afterAll)
140 | require.True(t, suite.testSome1)
141 | }
142 |
143 | type TestSuiteStartTimeOfConsistentTests struct {
144 | Suite
145 | }
146 |
147 | func (s *TestSuiteStartTimeOfConsistentTests) TestSome1(t provider.T) {
148 | t.WithNewStep("step 1", func(sCtx provider.StepCtx) {
149 | time.Sleep(1 * time.Second)
150 | })
151 | }
152 |
153 | func (s *TestSuiteStartTimeOfConsistentTests) TestSome2(t provider.T) {
154 | t.WithNewStep("step 2", func(sCtx provider.StepCtx) {
155 | time.Sleep(1 * time.Second)
156 | })
157 | }
158 |
159 | func TestSuiteRunner_StartTimeAndDurationOfConsistentTests(t *testing.T) {
160 | allureDir := "./allure-results"
161 | defer os.RemoveAll(allureDir)
162 |
163 | suite := new(TestSuiteStartTimeOfConsistentTests)
164 | r := runner.NewSuiteRunner(t, "packageName", "suiteName", suite)
165 | results := r.RunTests().GetAllTestResults()
166 |
167 | require.True(t, results[1].GetResult().Start-results[0].GetResult().Stop <= 15)
168 | require.Equal(t, time.UnixMilli(results[0].GetResult().Stop-results[0].GetResult().Start).Second(), 1)
169 | require.Equal(t, time.UnixMilli(results[1].GetResult().Stop-results[1].GetResult().Start).Second(), 1)
170 | }
171 |
--------------------------------------------------------------------------------
/pkg/framework/suite/suite_test.go:
--------------------------------------------------------------------------------
1 | package suite
2 |
3 | import (
4 | "os"
5 | "sync"
6 | "testing"
7 |
8 | "github.com/stretchr/testify/require"
9 |
10 | "github.com/ozontech/allure-go/pkg/framework/provider"
11 | "github.com/ozontech/allure-go/pkg/framework/runner"
12 | )
13 |
14 | func TestSuite_SetRunner(t *testing.T) {
15 | suite := Suite{}
16 | r := runner.NewRunner(new(testing.T), "suiteName")
17 | suite.SetRunner(r)
18 | require.Equal(t, r, suite.runner)
19 | }
20 |
21 | func TestSuite_GetRunner(t *testing.T) {
22 | r := runner.NewRunner(new(testing.T), "suiteName")
23 | suite := Suite{runner: r}
24 | require.Equal(t, r, suite.GetRunner())
25 | }
26 |
27 | type TestSuiteRunSuite struct {
28 | Suite
29 | s2 *TestSuiteRunSuite2
30 | }
31 |
32 | func (s *TestSuiteRunSuite) TestSome(t provider.T) {
33 | s.s2 = new(TestSuiteRunSuite2)
34 | s.RunSuite(t, s.s2)
35 | }
36 |
37 | type TestSuiteRunSuite2 struct {
38 | Suite
39 |
40 | wg sync.WaitGroup
41 | testSome1 bool
42 |
43 | beforeAll bool
44 | beforeEach bool
45 | afterEach bool
46 | afterAll bool
47 | }
48 |
49 | func (s *TestSuiteRunSuite2) BeforeAll(t provider.T) {
50 | s.beforeAll = true
51 | }
52 |
53 | func (s *TestSuiteRunSuite2) BeforeEach(t provider.T) {
54 | s.beforeEach = true
55 | }
56 |
57 | func (s *TestSuiteRunSuite2) AfterEach(t provider.T) {
58 | s.afterEach = true
59 | }
60 |
61 | func (s *TestSuiteRunSuite2) AfterAll(t provider.T) {
62 | s.afterAll = true
63 | }
64 |
65 | func (s *TestSuiteRunSuite2) TestSome(t provider.T) {
66 | s.testSome1 = true
67 | }
68 |
69 | func TestSuite_RunSuite(t *testing.T) {
70 | allureDir := "./allure-results"
71 | defer os.RemoveAll(allureDir)
72 |
73 | suite := new(TestSuiteRunSuite)
74 | mockT := &suiteRunnerTMock{t: t}
75 | r := runner.NewSuiteRunner(mockT, "packageName", "suiteName", suite)
76 | r.RunTests()
77 |
78 | // subtests have been run
79 | require.True(t, suite.s2.testSome1)
80 | require.True(t, suite.s2.beforeEach)
81 | require.True(t, suite.s2.beforeAll)
82 | require.True(t, suite.s2.afterEach)
83 | require.True(t, suite.s2.afterAll)
84 | }
85 |
--------------------------------------------------------------------------------