Skip to content

Commit 68cc813

Browse files
authored
Add nested steps support and custom step methods (#6)
1 parent 8dff832 commit 68cc813

File tree

6 files changed

+132
-14
lines changed

6 files changed

+132
-14
lines changed

allure-ruby-commons/lib/allure-ruby-commons.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,32 @@ def add_link(url:, name: nil, type: "custom")
137137
def add_attachment(name:, source:, type:, test_case: false)
138138
lifecycle.add_attachment(name: name, source: source, type: type, test_case: test_case)
139139
end
140+
141+
# Add step with provided name and optional status to current test step, fixture or test case
142+
# @param [String] name
143+
# @param [Symbol] status <Allure::Status>, <Allure::Status::PASSED> by default
144+
# @return [void]
145+
def step(name:, status: nil)
146+
lifecycle.add_test_step(StepResult.new(name: name, status: status || Status::PASSED, stage: Stage::FINISHED))
147+
end
148+
149+
# Run passed block as step with given name
150+
# @param [String] name
151+
# @yield [] step block
152+
# @return [void]
153+
def run_step(name)
154+
lifecycle.start_test_step(StepResult.new(name: name, stage: Stage::RUNNING))
155+
yield
156+
lifecycle.update_test_step { |step| step.status = Status::PASSED }
157+
rescue => e
158+
lifecycle.update_test_step do |step|
159+
step.status = ResultUtils.status(e)
160+
step.status_details = ResultUtils.status_details(e)
161+
end
162+
raise(e)
163+
ensure
164+
lifecycle.stop_test_step
165+
end
140166
end
141167
end
142168
# rubocop:enable Naming/FileName

allure-ruby-commons/lib/allure_ruby_commons/allure_lifecycle.rb

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
module Allure
44
# Main class for creating and writing allure results
55
class AllureLifecycle
6+
def initialize
7+
@step_context = []
8+
end
9+
610
# Start test result container
711
# @param [Allure::TestResultContainer] test_result_container
812
# @return [Allure::TestResultContainer]
@@ -42,6 +46,7 @@ def stop_test_container
4246
# @param [Allure::TestResult] test_result
4347
# @return [Allure::TestResult]
4448
def start_test_case(test_result)
49+
clear_step_context
4550
unless @current_test_result_container
4651
return logger.error("Could not start test case, test container is not started")
4752
end
@@ -75,6 +80,7 @@ def stop_test_case
7580
@current_test_case.stage = Stage::FINISHED
7681
file_writer.write_test_result(@current_test_case)
7782
clear_current_test_case
83+
clear_step_context
7884
end
7985

8086
# Start test step and add to current test case
@@ -85,8 +91,8 @@ def start_test_step(step_result)
8591

8692
step_result.start = ResultUtils.timestamp
8793
step_result.stage = Stage::RUNNING
88-
@current_test_case.steps.push(step_result)
89-
@current_test_step = step_result
94+
add_test_step(step_result)
95+
step_result
9096
end
9197

9298
# @example Update current test step
@@ -97,19 +103,19 @@ def start_test_step(step_result)
97103
# @yieldreturn [void]
98104
# @return [void]
99105
def update_test_step
100-
return logger.error("Could not update test step, no step is running") unless @current_test_step
106+
return logger.error("Could not update test step, no step is running") unless current_test_step
101107

102-
yield(@current_test_step)
108+
yield(current_test_step)
103109
end
104110

105111
# Stop current test step
106112
# @return [void]
107113
def stop_test_step
108-
return logger.error("Could not stop test step, no step is running") unless @current_test_step
114+
return logger.error("Could not stop test step, no step is running") unless current_test_step
109115

110-
@current_test_step.stop = ResultUtils.timestamp
111-
@current_test_step.stage = Stage::FINISHED
112-
clear_current_test_step
116+
current_test_step.stop = ResultUtils.timestamp
117+
current_test_step.stage = Stage::FINISHED
118+
clear_last_test_step
113119
end
114120

115121
# Start prepare fixture
@@ -134,6 +140,7 @@ def start_tear_down_fixture(fixture_result)
134140
# @param [Allure::FixtureResult] fixture_result
135141
# @return [Allure::FixtureResult]
136142
def start_fixture(fixture_result)
143+
clear_step_context
137144
unless @current_test_result_container
138145
logger.error("Could not start fixture, test container is not started")
139146
return false
@@ -162,6 +169,7 @@ def stop_fixture
162169
@current_fixture.stop = ResultUtils.timestamp
163170
@current_fixture.stage = Stage::FINISHED
164171
clear_current_fixture
172+
clear_step_context
165173
end
166174

167175
# Add attachment to current test or step
@@ -199,6 +207,15 @@ def write_attachment(source, attachment)
199207
file_writer.write_attachment(source, attachment)
200208
end
201209

210+
# Add step to current fixture|step|test case
211+
# @param [Allure::StepResult] step_result
212+
# @return [Allure::StepResult]
213+
def add_test_step(step_result)
214+
current_executable.steps.push(step_result)
215+
@step_context.push(step_result)
216+
step_result
217+
end
218+
202219
private
203220

204221
def logger
@@ -210,7 +227,7 @@ def file_writer
210227
end
211228

212229
def current_executable
213-
@current_test_step || @current_fixture || @current_test_case
230+
current_test_step || @current_fixture || @current_test_case
214231
end
215232

216233
def clear_current_test_container
@@ -221,8 +238,16 @@ def clear_current_test_case
221238
@current_test_case = nil
222239
end
223240

224-
def clear_current_test_step
225-
@current_test_step = nil
241+
def current_test_step
242+
@step_context.last
243+
end
244+
245+
def clear_last_test_step
246+
@step_context.pop
247+
end
248+
249+
def clear_step_context
250+
@step_context.clear
226251
end
227252

228253
def clear_current_fixture

allure-ruby-commons/lib/allure_ruby_commons/result_utils.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def status(exception)
127127
# @param [Exception] exception
128128
# @return [Hash<Symbol, String>]
129129
def status_details(exception)
130-
{ message: exception.message, trace: exception.backtrace&.join("\n") }
130+
StatusDetails.new(message: exception.message, trace: exception.backtrace&.join("\n"))
131131
end
132132

133133
private

allure-ruby-commons/spec/unit/allure_spec.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,36 @@
8181
expect(attachment.source).to include(".txt")
8282
end
8383
end
84+
85+
it "adds custom step" do
86+
test_step = Allure.step(name: "Custom step", status: Allure::Status::FAILED)
87+
expect(@test_case.steps.last).to eq(test_step)
88+
end
89+
90+
it "runs custom step" do
91+
Allure.run_step("Custom step") do
92+
1 + 1
93+
end
94+
test_step = @test_case.steps.last
95+
aggregate_failures "custom step should be handled correctly" do
96+
expect(test_step.name).to eq("Custom step")
97+
expect(test_step.status).to eq(Allure::Status::PASSED)
98+
expect(test_step.stage).to eq(Allure::Stage::FINISHED)
99+
end
100+
end
101+
102+
it "correctly handles custom step failure" do
103+
Allure.run_step("Custom step") do
104+
raise StandardError.new("Error")
105+
end
106+
rescue
107+
test_step = @test_case.steps.last
108+
aggregate_failures "custom step should be handled correctly" do
109+
expect(test_step.name).to eq("Custom step")
110+
expect(test_step.status).to eq(Allure::Status::BROKEN)
111+
expect(test_step.stage).to eq(Allure::Stage::FINISHED)
112+
expect(test_step.status_details.message).to eq("Error")
113+
end
114+
end
84115
end
85116
end

allure-ruby-commons/spec/unit/result_utils_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
raise error
1717
rescue => e
1818
status_details = Allure::ResultUtils.status_details(e)
19-
expect(status_details[:message]).to eq("Error")
20-
expect(status_details[:message]).not_to be_empty
19+
expect(status_details.message).to eq("Error")
20+
expect(status_details.message).not_to be_empty
2121
end
2222
end

allure-ruby-commons/spec/unit/test_step_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,27 @@
2020
end
2121
end
2222

23+
it "starts nested step" do
24+
start_test_step(name: "Nested step name", descrption: "step description")
25+
expect(@test_step.steps.last.name).to eq("Nested step name")
26+
end
27+
2328
it "updates test step" do
2429
lifecycle.update_test_step { |step| step.status = Allure::Status::SKIPPED }
2530

2631
expect(@test_step.status).to eq(Allure::Status::SKIPPED)
2732
end
2833

34+
it "updates nested step" do
35+
start_test_step(name: "Nested step name", descrption: "step description")
36+
lifecycle.update_test_step { |step| step.status = Allure::Status::SKIPPED }
37+
38+
aggregate_failures "steps should have correct status" do
39+
expect(@test_step.steps.last.status).to eq(Allure::Status::SKIPPED)
40+
expect(@test_step.status).to eq(Allure::Status::BROKEN) # default status for unfinished step
41+
end
42+
end
43+
2944
it "stops test step" do
3045
lifecycle.stop_test_step
3146

@@ -34,6 +49,27 @@
3449
expect(@test_step.stage).to eq(Allure::Stage::FINISHED)
3550
end
3651
end
52+
53+
it "stops nested step" do
54+
start_test_step(name: "Nested step name", descrption: "step description")
55+
lifecycle.stop_test_step
56+
57+
aggregate_failures "should have stopped only nested step" do
58+
expect(@test_step.steps.last.stage).to eq(Allure::Stage::FINISHED)
59+
expect(@test_step.stage).to eq(Allure::Stage::RUNNING)
60+
end
61+
end
62+
63+
it "stops parent step" do
64+
start_test_step(name: "Nested step name", descrption: "step description")
65+
lifecycle.stop_test_step
66+
lifecycle.stop_test_step
67+
68+
aggregate_failures "should have stopped both step" do
69+
expect(@test_step.steps.last.stage).to eq(Allure::Stage::FINISHED)
70+
expect(@test_step.stage).to eq(Allure::Stage::FINISHED)
71+
end
72+
end
3773
end
3874

3975
context "logs error" do

0 commit comments

Comments
 (0)