Skip to content

Commit

Permalink
Add code reference for Examples scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
HardNorth committed Dec 14, 2023
1 parent 11dbf97 commit 5e874bc
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 25 deletions.
48 changes: 48 additions & 0 deletions src/main/java/com/epam/reportportal/karate/KarateUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2021 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.epam.reportportal.karate;

import javax.annotation.Nonnull;
import java.util.Map;
import java.util.stream.Collectors;

/**
* Set of useful utils related to Karate -> ReportPortal integration
*/
public class KarateUtils {

private KarateUtils() {
throw new AssertionError("No instances should exist for the class!");
}

private static final String PARAMETER_ITEMS_START = "[";
private static final String PARAMETER_ITEMS_END = "]";
private static final String PARAMETER_ITEMS_DELIMITER = ";";
private static final String KEY_VALUE_SEPARATOR = ":";

/**
* Create a String from a parameter Map to be used as a test key and title
*
* @param example a map of parameters: name->value
* @return a formatted string of parameters
*/
public static String formatExampleKey(@Nonnull final Map<String, Object> example) {
return example.entrySet()
.stream()
.map(e -> e.getKey() + KEY_VALUE_SEPARATOR + e.getValue().toString())
.collect(Collectors.joining(PARAMETER_ITEMS_DELIMITER, PARAMETER_ITEMS_START, PARAMETER_ITEMS_END));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

public class ReportPortalPublisher {
public static final String SCENARIO_CODE_REFERENCE_PATTERN = "%s/[SCENARIO:%s]";
public static final String EXAMPLE_CODE_REFERENCE_PATTERN = "%s/[EXAMPLE:%s%s]";

private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalPublisher.class);
private final ConcurrentHashMap<String, Maybe<String>> featureIdMap = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -116,7 +117,8 @@ protected String getCodeRef(Scenario scenario) {
return String.format(SCENARIO_CODE_REFERENCE_PATTERN, scenario.getFeature().getResource().getRelativePath(),
scenario.getName());
} else {
return null;
return String.format(EXAMPLE_CODE_REFERENCE_PATTERN, scenario.getFeature().getResource().getRelativePath(),
scenario.getName(), KarateUtils.formatExampleKey(scenario.getExampleData()));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.epam.reportportal.karate.coderef;

import com.epam.reportportal.karate.utils.TestUtils;
import com.epam.reportportal.listeners.ItemType;
import com.epam.reportportal.service.ReportPortal;
import com.epam.reportportal.service.ReportPortalClient;
import com.epam.reportportal.util.test.CommonUtils;
import com.epam.ta.reportportal.ws.model.StartTestItemRQ;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static com.epam.reportportal.karate.utils.TestUtils.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.*;

public class ExamplesCodeRefTest {
private final String featureId = CommonUtils.namedId("feature_");
private final List<String> exampleIds = Stream.generate(() -> CommonUtils.namedId("example_")).limit(2)
.collect(Collectors.toList());
private final List<Pair<String, List<String>>> stepIds = exampleIds.stream()
.map(e -> Pair.of(e, Stream.generate(() -> CommonUtils.namedId("step_"))
.limit(2).collect(Collectors.toList())))
.collect(Collectors.toList());

private static final String EXAMPLE_CODE_REFERENCE_PATTERN = "feature/examples.feature/[EXAMPLE:Verify different maths[%s]]";
private static final String FIRST_EXAMPLE_CODE_REFERENCE = String.format(EXAMPLE_CODE_REFERENCE_PATTERN, "vara:2;varb:2;result:4");
private static final String SECOND_EXAMPLE_CODE_REFERENCE = String.format(EXAMPLE_CODE_REFERENCE_PATTERN, "vara:1;varb:2;result:3");

private final ReportPortalClient client = mock(ReportPortalClient.class);
private final ReportPortal rp = ReportPortal.create(client, standardParameters(), testExecutor());

@BeforeEach
public void setupMock() {
mockLaunch(client, null, featureId, stepIds);
mockBatchLogging(client);
}

@Test
public void test_examples_code_reference() {
var results = TestUtils.runAsReport(rp, "classpath:feature/examples.feature");
assertThat(results.getFailCount(), equalTo(0));

ArgumentCaptor<StartTestItemRQ> captor = ArgumentCaptor.forClass(StartTestItemRQ.class);
verify(client, times(1)).startTestItem(captor.capture());
verify(client, times(2)).startTestItem(same(featureId), captor.capture());
verify(client, times(2)).startTestItem(same(exampleIds.get(0)), captor.capture());
verify(client, times(2)).startTestItem(same(exampleIds.get(1)), captor.capture());

List<StartTestItemRQ> items = captor.getAllValues();
assertThat(items, hasSize(7));

StartTestItemRQ featureRq = items.get(0);

assertThat(featureRq.getType(), allOf(notNullValue(), equalTo(ItemType.STORY.name())));

StartTestItemRQ firstScenarioRq = items.get(1);
assertThat(firstScenarioRq.getType(), allOf(notNullValue(), equalTo(ItemType.STEP.name())));
assertThat(firstScenarioRq.getCodeRef(), allOf(notNullValue(), equalTo(FIRST_EXAMPLE_CODE_REFERENCE)));

StartTestItemRQ secondScenarioRq = items.get(2);
assertThat(secondScenarioRq.getType(), allOf(notNullValue(), equalTo(ItemType.STEP.name())));
assertThat(secondScenarioRq.getCodeRef(), allOf(notNullValue(), equalTo(SECOND_EXAMPLE_CODE_REFERENCE)));

List<StartTestItemRQ> stepRqs = items.subList(3, items.size());
IntStream.range(0, stepRqs.size()).forEach(i -> {
StartTestItemRQ step = stepRqs.get(i);
assertThat(step.getType(), allOf(notNullValue(), equalTo(ItemType.STEP.name())));
assertThat(step.isHasStats(), equalTo(Boolean.FALSE));
});
}
}
48 changes: 24 additions & 24 deletions src/test/java/com/epam/reportportal/karate/utils/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,51 +60,51 @@ public static ListenerParameters standardParameters() {
}

public static void mockLaunch(@Nonnull final ReportPortalClient client, @Nullable final String launchUuid,
@Nullable final String storyUuid, @Nonnull String testClassUuid,
@Nullable final String featureUuid, @Nonnull String scenarioUuid,
@Nonnull String stepUuid) {
mockLaunch(client, launchUuid, storyUuid, testClassUuid, Collections.singleton(stepUuid));
mockLaunch(client, launchUuid, featureUuid, scenarioUuid, Collections.singleton(stepUuid));
}

public static void mockLaunch(@Nonnull final ReportPortalClient client, @Nullable final String launchUuid,
@Nullable final String storyUuid, @Nonnull String testClassUuid,
@Nullable final String featureUuid, @Nonnull String scenarioUuid,
@Nonnull Collection<String> stepList) {
mockLaunch(client, launchUuid, storyUuid, Collections.singletonList(Pair.of(testClassUuid, stepList)));
mockLaunch(client, launchUuid, featureUuid, Collections.singletonList(Pair.of(scenarioUuid, stepList)));
}

public static <T extends Collection<String>> void mockLaunch(
@Nonnull final ReportPortalClient client, @Nullable final String launchUuid,
@Nullable final String storyUuid, @Nonnull final Collection<Pair<String, T>> testSteps) {
@Nullable final String featureUuid, @Nonnull final Collection<Pair<String, T>> scenarioSteps) {
String launch = ofNullable(launchUuid).orElse(CommonUtils.namedId("launch_"));
when(client.startLaunch(any())).thenReturn(Maybe.just(new StartLaunchRS(launch, 1L)));
when(client.finishLaunch(eq(launch), any())).thenReturn(Maybe.just(new OperationCompletionRS()));

mockFeature(client, storyUuid, testSteps);
mockFeature(client, featureUuid, scenarioSteps);
}

public static <T extends Collection<String>> void mockFeature(
@Nonnull final ReportPortalClient client, @Nullable final String storyUuid,
@Nonnull final Collection<Pair<String, T>> testSteps) {
String rootItemId = ofNullable(storyUuid).orElseGet(() -> CommonUtils.namedId(ROOT_SUITE_PREFIX));
mockFeatures(client, Collections.singletonList(Pair.of(rootItemId, testSteps)));
@Nonnull final ReportPortalClient client, @Nullable final String featureUuid,
@Nonnull final Collection<Pair<String, T>> scenarioSteps) {
String rootItemId = ofNullable(featureUuid).orElseGet(() -> CommonUtils.namedId(ROOT_SUITE_PREFIX));
mockFeatures(client, Collections.singletonList(Pair.of(rootItemId, scenarioSteps)));
}

@SuppressWarnings("unchecked")
public static <T extends Collection<String>> void mockFeatures(
@Nonnull final ReportPortalClient client,
@Nonnull final List<Pair<String, Collection<Pair<String, T>>>> stories) {
if (stories.isEmpty()) {
@Nonnull final List<Pair<String, Collection<Pair<String, T>>>> features) {
if (features.isEmpty()) {
return;
}
String firstStory = stories.get(0).getKey();
Maybe<ItemCreatedRS> first = Maybe.just(new ItemCreatedRS(firstStory, firstStory));
Maybe<ItemCreatedRS>[] other = (Maybe<ItemCreatedRS>[]) stories.subList(1, stories.size())
String firstFeature = features.get(0).getKey();
Maybe<ItemCreatedRS> first = Maybe.just(new ItemCreatedRS(firstFeature, firstFeature));
Maybe<ItemCreatedRS>[] other = (Maybe<ItemCreatedRS>[]) features.subList(1, features.size())
.stream()
.map(Pair::getKey)
.map(s -> Maybe.just(new ItemCreatedRS(s, s)))
.toArray(Maybe[]::new);
when(client.startTestItem(any())).thenReturn(first, other);

stories.forEach(i -> {
features.forEach(i -> {
Maybe<OperationCompletionRS> rootFinishMaybe = Maybe.just(new OperationCompletionRS());
when(client.finishTestItem(same(i.getKey()), any())).thenReturn(rootFinishMaybe);
mockScenario(client, i.getKey(), i.getValue());
Expand All @@ -113,28 +113,28 @@ public static <T extends Collection<String>> void mockFeatures(

@SuppressWarnings("unchecked")
public static <T extends Collection<String>> void mockScenario(
@Nonnull final ReportPortalClient client, @Nonnull final String storyUuid,
@Nonnull final Collection<Pair<String, T>> testSteps) {
List<Maybe<ItemCreatedRS>> testResponses = testSteps.stream()
@Nonnull final ReportPortalClient client, @Nonnull final String featureUuid,
@Nonnull final Collection<Pair<String, T>> scenarioSteps) {
List<Maybe<ItemCreatedRS>> testResponses = scenarioSteps.stream()
.map(Pair::getKey)
.map(uuid -> Maybe.just(new ItemCreatedRS(uuid, uuid)))
.collect(Collectors.toList());

Maybe<ItemCreatedRS> first = testResponses.get(0);
Maybe<ItemCreatedRS>[] other = testResponses.subList(1, testResponses.size()).toArray(new Maybe[0]);
when(client.startTestItem(same(storyUuid), any())).thenReturn(first, other);
when(client.startTestItem(same(featureUuid), any())).thenReturn(first, other);

testSteps.forEach(test -> {
String testClassUuid = test.getKey();
scenarioSteps.forEach(test -> {
String scenarioUuid = test.getKey();
List<Maybe<ItemCreatedRS>> stepResponses = test.getValue()
.stream()
.map(uuid -> Maybe.just(new ItemCreatedRS(uuid, uuid)))
.collect(Collectors.toList());
when(client.finishTestItem(same(testClassUuid), any())).thenReturn(Maybe.just(new OperationCompletionRS()));
when(client.finishTestItem(same(scenarioUuid), any())).thenReturn(Maybe.just(new OperationCompletionRS()));
if (!stepResponses.isEmpty()) {
Maybe<ItemCreatedRS> myFirst = stepResponses.get(0);
Maybe<ItemCreatedRS>[] myOther = stepResponses.subList(1, stepResponses.size()).toArray(new Maybe[0]);
when(client.startTestItem(same(testClassUuid), any())).thenReturn(myFirst, myOther);
when(client.startTestItem(same(scenarioUuid), any())).thenReturn(myFirst, myOther);
new HashSet<>(test.getValue()).forEach(testMethodUuid -> when(
client.finishTestItem(same(testMethodUuid),
any()
Expand Down
10 changes: 10 additions & 0 deletions src/test/resources/feature/examples.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Feature: math tests with examples

Scenario Outline: Verify different maths
Given def mathResult = vara + varb
Then assert mathResult == result

Examples:
| vara! | varb! | result! |
| 2 | 2 | 4 |
| 1 | 2 | 3 |

0 comments on commit 5e874bc

Please sign in to comment.