Skip to content

Commit 8297ca5

Browse files
committed
#17: Implemented handler type
- added Tree handling strategy - updated documentation
1 parent 273408a commit 8297ca5

File tree

11 files changed

+274
-71
lines changed

11 files changed

+274
-71
lines changed

README.md

+16
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,22 @@ Custom `NarrativeFormatter` should be registered via configuration
138138
ReportIntegrationConfig.narrativeFormatter = new NumberedListFormatter();
139139
```
140140

141+
**Handler type (expiremental feature)**
142+
143+
Integration provides two strategies of storing Serenity's test data to Report Portal facility:
144+
- FLAT (default behaviour) - Represents steps data as plain logs emmited to the test scope
145+
- TREE - Reconstructs steps structure as a tree representation in RP
146+
147+
Report Portal has a few limitations regurding to flexible nested structures support for now. As a result test report may contain some inaccuracate data.
148+
E. g. test count for launch will show total number of tests + total number of steps.
149+
150+
Nevertheless `TREE` configuration allows to get additional features with RP. E. g. integrated RP test analisys facility will be changed from test to step.
151+
152+
Handler type may be changed with following configuration
153+
```
154+
ReportIntegrationConfig.handlerType = HandlerType.TREE;
155+
```
156+
141157
> **Notice**
142158
All integration configurations should be provided before Serenity facility init (For example on `@BeforeClass` method on the parent test class for jUnit style tests). Otherwise default values will be used.
143159

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
<dependency>
6060
<groupId>com.epam.reportportal</groupId>
6161
<artifactId>client-java</artifactId>
62-
<version>4.0.6</version>
62+
<version>4.0.7</version>
6363
</dependency>
6464
<dependency>
6565
<groupId>com.epam.reportportal</groupId>

src/main/java/com/github/invictum/reportportal/ReportIntegrationConfig.java

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.github.invictum.reportportal;
22

3+
import com.github.invictum.reportportal.handler.HandlerType;
4+
35
/**
46
* Static configuration entry point for integration.
57
* Allows to redefine configuration for integration module. Configuration should be defined only once, before tests invocation.
@@ -22,6 +24,11 @@ private ReportIntegrationConfig() {
2224
*/
2325
public static NarrativeFormatter narrativeFormatter = new NarrativeBulletListFormatter();
2426

27+
/**
28+
* Defines handler type used for Serenity's {@link net.thucydides.core.model.TestOutcome} representation in RP
29+
*/
30+
public static HandlerType handlerType = HandlerType.FLAT;
31+
2532
@Deprecated
2633
/* Use profile variable to set config directly instead */
2734
public static void useProfile(StepsSetProfile profile) {

src/main/java/com/github/invictum/reportportal/ReportPortalListener.java

+12-69
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,48 @@
11
package com.github.invictum.reportportal;
22

3-
import com.epam.reportportal.service.Launch;
4-
import com.epam.ta.reportportal.ws.model.FinishTestItemRQ;
5-
import com.epam.ta.reportportal.ws.model.StartTestItemRQ;
6-
import com.github.invictum.reportportal.injector.IntegrationInjector;
7-
import com.google.inject.Inject;
8-
import io.reactivex.Maybe;
3+
import com.github.invictum.reportportal.handler.FlatHandler;
4+
import com.github.invictum.reportportal.handler.Handler;
5+
import com.github.invictum.reportportal.handler.HandlerType;
6+
import com.github.invictum.reportportal.handler.TreeHandler;
97
import net.thucydides.core.model.DataTable;
108
import net.thucydides.core.model.Story;
119
import net.thucydides.core.model.TestOutcome;
12-
import net.thucydides.core.requirements.annotations.NarrativeFinder;
1310
import net.thucydides.core.steps.ExecutedStepDescription;
1411
import net.thucydides.core.steps.StepFailure;
1512
import net.thucydides.core.steps.StepListener;
1613

17-
import java.time.Duration;
18-
import java.util.Calendar;
19-
import java.util.Date;
2014
import java.util.Map;
2115

2216
public class ReportPortalListener implements StepListener {
2317

24-
@Inject
25-
private Launch launch;
26-
27-
@Inject
28-
private StepProcessorsHolder holder;
29-
30-
@Inject
31-
private NarrativeFormatter narrativeFormatter;
32-
33-
private Maybe<String> suiteId = null;
34-
private Maybe<String> testId = null;
18+
private Handler handler;
3519

3620
public ReportPortalListener() {
37-
IntegrationInjector.getInjector().injectMembers(this);
21+
handler = (ReportIntegrationConfig.handlerType == HandlerType.FLAT) ? new FlatHandler() : new TreeHandler();
3822
}
3923

4024
public void testSuiteStarted(Class<?> storyClass) {
41-
if (suiteId == null) {
42-
StartTestItemRQ startSuite = new StartTestItemRQ();
43-
startSuite.setType(ItemType.SUITE.key());
44-
startSuite.setName(storyClass.getSimpleName());
45-
startSuite.setStartTime(Calendar.getInstance().getTime());
46-
/* Add narrative to description if present */
47-
if (NarrativeFinder.forClass(storyClass).isPresent()) {
48-
String description = narrativeFormatter.format(NarrativeFinder.forClass(storyClass).get().text());
49-
startSuite.setDescription(description);
50-
}
51-
suiteId = launch.startTestItem(startSuite);
52-
}
25+
handler.startSuite(storyClass);
5326
}
5427

5528
public void testSuiteStarted(Story story) {
56-
if (suiteId == null) {
57-
StartTestItemRQ startSuite = new StartTestItemRQ();
58-
startSuite.setType(ItemType.SUITE.key());
59-
startSuite.setName(story.getDisplayName());
60-
startSuite.setStartTime(Calendar.getInstance().getTime());
61-
startSuite.setDescription(story.getNarrative());
62-
suiteId = launch.startTestItem(startSuite);
63-
}
29+
handler.startSuite(story);
6430
}
6531

6632
public void testSuiteFinished() {
67-
if (suiteId != null) {
68-
FinishTestItemRQ finishSuite = new FinishTestItemRQ();
69-
finishSuite.setEndTime(Calendar.getInstance().getTime());
70-
finishSuite.setStatus(Status.PASSED.toString());
71-
launch.finishTestItem(suiteId, finishSuite);
72-
suiteId = null;
73-
}
33+
handler.finishSuite();
7434
}
7535

7636
public void testStarted(String description) {
77-
if (testId == null) {
78-
StartTestItemRQ startTest = new StartTestItemRQ();
79-
startTest.setType(ItemType.TEST.key());
80-
startTest.setName(description);
81-
startTest.setStartTime(Calendar.getInstance().getTime());
82-
testId = launch.startTestItem(suiteId, startTest);
83-
}
37+
handler.startTest(description);
8438
}
8539

8640
public void testStarted(String description, String id) {
87-
testStarted(description);
41+
handler.startTest(description);
8842
}
8943

9044
public void testFinished(TestOutcome result) {
91-
if (testId != null) {
92-
/* Proceed all steps */
93-
result.getFlattenedTestSteps().forEach(step -> holder.proceed(step));
94-
/* Finish active test */
95-
FinishTestItemRQ finishTest = new FinishTestItemRQ();
96-
Date endDate = Date.from(result.getStartTime().plus(Duration.ofMillis(result.getDuration())).toInstant());
97-
finishTest.setEndTime(endDate);
98-
finishTest.setStatus(Status.mapTo(result.getResult()).toString());
99-
finishTest.setTags(Utils.refineTags(result));
100-
launch.finishTestItem(testId, finishTest);
101-
testId = null;
102-
}
45+
handler.finishTest(result);
10346
}
10447

10548
public void testRetried() {

src/main/java/com/github/invictum/reportportal/Utils.java

+10
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ public static Date stepEndDate(TestStep step) {
3232
return Date.from(endTimeZoned.toInstant());
3333
}
3434

35+
/**
36+
* Calculates step's start time
37+
*
38+
* @param step to calculate time for
39+
* @return step start time in {@link Date} format
40+
*/
41+
public static Date stepStartDate(TestStep step) {
42+
return Date.from(step.getStartTime().toInstant());
43+
}
44+
3545
/**
3646
* Refines a set of tags represented with strings.
3747
* Tags with story type is skipped.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package com.github.invictum.reportportal.handler;
2+
3+
import com.epam.reportportal.service.Launch;
4+
import com.epam.ta.reportportal.ws.model.FinishTestItemRQ;
5+
import com.epam.ta.reportportal.ws.model.StartTestItemRQ;
6+
import com.github.invictum.reportportal.*;
7+
import com.github.invictum.reportportal.injector.IntegrationInjector;
8+
import com.google.inject.Inject;
9+
import io.reactivex.Maybe;
10+
import net.thucydides.core.model.Story;
11+
import net.thucydides.core.model.TestOutcome;
12+
import net.thucydides.core.requirements.annotations.NarrativeFinder;
13+
14+
import java.time.Duration;
15+
import java.util.Calendar;
16+
import java.util.Date;
17+
18+
/**
19+
* Handler builds Serenity's {@link TestOutcome} in Report Portal as flat sequence of logs
20+
*/
21+
public class FlatHandler implements Handler {
22+
23+
@Inject
24+
Launch launch;
25+
26+
@Inject
27+
private NarrativeFormatter narrativeFormatter;
28+
29+
@Inject
30+
private StepProcessorsHolder holder;
31+
32+
Maybe<String> suiteId;
33+
Maybe<String> testId;
34+
35+
public FlatHandler() {
36+
IntegrationInjector.getInjector().injectMembers(this);
37+
}
38+
39+
@Override
40+
public void startSuite(Class<?> storyClass) {
41+
if (suiteId == null) {
42+
StartTestItemRQ startSuite = new StartTestItemRQ();
43+
startSuite.setType(ItemType.SUITE.key());
44+
startSuite.setName(storyClass.getSimpleName());
45+
startSuite.setStartTime(Calendar.getInstance().getTime());
46+
/* Add narrative to description if present */
47+
if (NarrativeFinder.forClass(storyClass).isPresent()) {
48+
String description = narrativeFormatter.format(NarrativeFinder.forClass(storyClass).get().text());
49+
startSuite.setDescription(description);
50+
}
51+
suiteId = launch.startTestItem(startSuite);
52+
}
53+
}
54+
55+
@Override
56+
public void startSuite(Story story) {
57+
if (suiteId == null) {
58+
StartTestItemRQ startSuite = new StartTestItemRQ();
59+
startSuite.setType(ItemType.SUITE.key());
60+
startSuite.setName(story.getDisplayName());
61+
startSuite.setStartTime(Calendar.getInstance().getTime());
62+
startSuite.setDescription(story.getNarrative());
63+
suiteId = launch.startTestItem(startSuite);
64+
}
65+
}
66+
67+
@Override
68+
public void finishSuite() {
69+
if (suiteId != null) {
70+
FinishTestItemRQ finishSuite = new FinishTestItemRQ();
71+
finishSuite.setEndTime(Calendar.getInstance().getTime());
72+
finishSuite.setStatus(Status.PASSED.toString());
73+
launch.finishTestItem(suiteId, finishSuite);
74+
suiteId = null;
75+
}
76+
}
77+
78+
@Override
79+
public void startTest(String description) {
80+
if (testId == null) {
81+
StartTestItemRQ startTest = new StartTestItemRQ();
82+
startTest.setType(ItemType.TEST.key());
83+
startTest.setName(description);
84+
startTest.setStartTime(Calendar.getInstance().getTime());
85+
testId = launch.startTestItem(suiteId, startTest);
86+
}
87+
}
88+
89+
@Override
90+
public void finishTest(TestOutcome result) {
91+
if (testId != null) {
92+
/* Proceed all steps */
93+
result.getFlattenedTestSteps().forEach(step -> holder.proceed(step));
94+
/* Finish active test */
95+
FinishTestItemRQ finishTest = new FinishTestItemRQ();
96+
Date endDate = Date.from(result.getStartTime().plus(Duration.ofMillis(result.getDuration())).toInstant());
97+
finishTest.setEndTime(endDate);
98+
finishTest.setStatus(Status.mapTo(result.getResult()).toString());
99+
finishTest.setTags(Utils.refineTags(result));
100+
launch.finishTestItem(testId, finishTest);
101+
testId = null;
102+
}
103+
}
104+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.github.invictum.reportportal.handler;
2+
3+
import net.thucydides.core.model.Story;
4+
import net.thucydides.core.model.TestOutcome;
5+
6+
/**
7+
* Defines strategy used for processing Serenity test related events
8+
*/
9+
public interface Handler {
10+
/**
11+
* Starts a new suite for class
12+
*
13+
* @param storyClass to start suite for
14+
*/
15+
void startSuite(Class<?> storyClass);
16+
17+
/**
18+
* Starts a new suite for story
19+
*
20+
* @param story to start suite for
21+
*/
22+
void startSuite(Story story);
23+
24+
/**
25+
* Finish currently active suite
26+
*/
27+
void finishSuite();
28+
29+
/**
30+
* Start a new test
31+
*
32+
* @param description to use for test
33+
*/
34+
void startTest(String description);
35+
36+
/**
37+
* Finalizes currently active test
38+
*
39+
* @param result used to build a test outcome
40+
*/
41+
void finishTest(TestOutcome result);
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.github.invictum.reportportal.handler;
2+
3+
/**
4+
* Describes available configuration options for {@link Handler} setup
5+
*/
6+
public enum HandlerType {
7+
/**
8+
* Builds steps structure as log entities (default behaviour)
9+
*/
10+
FLAT,
11+
12+
/**
13+
* Builds steps structure as a nested RP entities
14+
*/
15+
TREE
16+
}

0 commit comments

Comments
 (0)