Skip to content

Commit

Permalink
Table parameters handling
Browse files Browse the repository at this point in the history
  • Loading branch information
HardNorth committed Dec 20, 2023
1 parent 27c370c commit e5bfcce
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 102 deletions.
143 changes: 81 additions & 62 deletions src/main/java/com/epam/reportportal/karate/ReportPortalPublisher.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@

package com.epam.reportportal.karate;

import com.epam.reportportal.karate.enums.ItemLogLevelEnum;
import com.epam.reportportal.karate.enums.ItemStatusEnum;
import com.epam.reportportal.listeners.ItemStatus;
import com.epam.reportportal.listeners.ItemType;
import com.epam.reportportal.listeners.ListenerParameters;
import com.epam.reportportal.listeners.LogLevel;
Expand All @@ -26,7 +25,6 @@
import com.epam.reportportal.service.item.TestCaseIdEntry;
import com.epam.reportportal.utils.AttributeParser;
import com.epam.reportportal.utils.MemoizingSupplier;
import com.epam.reportportal.utils.ParameterUtils;
import com.epam.reportportal.utils.TestCaseIdUtils;
import com.epam.reportportal.utils.properties.SystemAttributesExtractor;
import com.epam.ta.reportportal.ws.model.FinishExecutionRQ;
Expand All @@ -50,6 +48,9 @@
import java.util.stream.Stream;

import static com.epam.reportportal.karate.ReportPortalUtils.AGENT_PROPERTIES_FILE;
import static com.epam.reportportal.utils.ParameterUtils.NULL_VALUE;
import static com.epam.reportportal.utils.ParameterUtils.formatParametersAsTable;
import static com.epam.reportportal.utils.markdown.MarkdownUtils.formatDataTable;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Optional.ofNullable;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
Expand Down Expand Up @@ -193,36 +194,6 @@ protected StartTestItemRQ buildStartTestItemRq(@Nonnull String name, @Nonnull Da
return rq;
}

/**
* Customize start step test item event/request
*
* @param step Karate's Step class instance
* @param scenario Karate's Scenario class instance
* @return request to ReportPortal
*/
protected StartTestItemRQ buildStartStepRq(@Nonnull Step step, Scenario scenario) {
String stepName = step.getPrefix() + " " + step.getText();
StartTestItemRQ rq = buildStartTestItemRq(stepName, getStepStartTime(stepStartTimeMap, stepId), ItemType.STEP);
rq.setHasStats(false);
if (step.isOutline()) {
List<ParameterResource> parameters = scenario
.getExampleData()
.entrySet()
.stream()
.filter(e -> Pattern.compile(String.format(VARIABLE_PATTERN, e.getKey())).matcher(step.getText()).find())
.map(e -> {
ParameterResource param = new ParameterResource();
param.setKey(e.getKey());
var value = ofNullable(e.getValue()).map(Object::toString).orElse(ParameterUtils.NULL_VALUE);
param.setValue(value);
return param;
})
.collect(Collectors.toList());
rq.setParameters(parameters);
}
return rq;
}

@Nullable
private Set<ItemAttributesRQ> toAttributes(@Nullable List<Tag> tags) {
Set<ItemAttributesRQ> attributes = ofNullable(tags).orElse(Collections.emptyList()).stream().flatMap(tag -> {
Expand Down Expand Up @@ -258,7 +229,7 @@ private List<ParameterResource> getParameters(@Nonnull Scenario scenario) {
return scenario.getExampleData().entrySet().stream().map(e -> {
ParameterResource parameterResource = new ParameterResource();
parameterResource.setKey(e.getKey());
parameterResource.setValue(ofNullable(e.getValue()).map(Object::toString).orElse(ParameterUtils.NULL_VALUE));
parameterResource.setValue(ofNullable(e.getValue()).map(Object::toString).orElse(NULL_VALUE));
return parameterResource;
}).collect(Collectors.toList());
}
Expand Down Expand Up @@ -289,10 +260,10 @@ protected StartTestItemRQ buildStartScenarioRq(@Nonnull ScenarioResult scenarioR
* @return request to ReportPortal
*/
protected FinishTestItemRQ buildFinishTestItemRq(@Nonnull Date endTime,
@Nonnull String status) {
@Nonnull ItemStatus status) {
FinishTestItemRQ rq = new FinishTestItemRQ();
rq.setEndTime(endTime);
rq.setStatus(status);
rq.setStatus(status.name());
return rq;
}

Expand Down Expand Up @@ -332,7 +303,7 @@ public void finishFeature(FeatureResult featureResult) {
}

FinishTestItemRQ rq = buildFinishTestItemRq(Calendar.getInstance().getTime(),
featureResult.isFailed() ? ItemStatusEnum.FAILED.toString() : ItemStatusEnum.PASSED.toString());
featureResult.isFailed() ? ItemStatus.FAILED : ItemStatus.PASSED);
//noinspection ReactiveStreamsUnusedPublisher
launch.get().finishTestItem(featureIdMap.remove(featureResult.getCallNameForReport()), rq);
}
Expand Down Expand Up @@ -361,32 +332,62 @@ public void finishScenario(ScenarioResult scenarioResult) {
}

FinishTestItemRQ rq = buildFinishTestItemRq(Calendar.getInstance().getTime(),
scenarioResult.getFailureMessageForDisplay() == null ? ItemStatusEnum.PASSED.toString() : ItemStatusEnum.FAILED.toString());
scenarioResult.getFailureMessageForDisplay() == null ? ItemStatus.PASSED : ItemStatus.FAILED);
Maybe<String> removedScenarioId = scenarioIdMap.remove(scenarioResult.getScenario().getName());
//noinspection ReactiveStreamsUnusedPublisher
launch.get().finishTestItem(removedScenarioId, rq);
}

/**
* Customize start step test item event/request
*
* @param stepResult Karate's StepResult class instance
* @param scenarioResult Karate's ScenarioResult class instance
* @return request to ReportPortal
*/
@Nonnull
protected StartTestItemRQ buildStartStepRq(@Nonnull StepResult stepResult, @Nonnull ScenarioResult scenarioResult) {
Step step = stepResult.getStep();
String stepName = step.getPrefix() + " " + step.getText();
StartTestItemRQ rq = buildStartTestItemRq(stepName, getStepStartTime(stepStartTimeMap, stepId), ItemType.STEP);
rq.setHasStats(false);
if (step.isOutline()) {
Scenario scenario = scenarioResult.getScenario();
List<ParameterResource> parameters = scenario
.getExampleData()
.entrySet()
.stream()
.filter(e -> Pattern.compile(String.format(VARIABLE_PATTERN, e.getKey())).matcher(step.getText()).find())
.map(e -> {
ParameterResource param = new ParameterResource();
param.setKey(e.getKey());
var value = ofNullable(e.getValue()).map(Object::toString).orElse(NULL_VALUE);
param.setValue(value);
return param;
})
.collect(Collectors.toList());
rq.setParameters(parameters);
}
return rq;
}

/**
* Start sending step data to ReportPortal
*
* @param stepResult step result
* @param scenarioResult scenario result
*/
public void startStep(StepResult stepResult, ScenarioResult scenarioResult) {
StartTestItemRQ stepRq = buildStartStepRq(stepResult.getStep(), scenarioResult.getScenario());
StartTestItemRQ stepRq = buildStartStepRq(stepResult, scenarioResult);
stepId = launch.get().startTestItem(scenarioIdMap.get(scenarioResult.getScenario().getName()), stepRq);
stepStartTimeMap.put(stepId, stepRq.getStartTime().getTime());
ofNullable(stepRq.getParameters())
.filter(params -> !params.isEmpty())
.ifPresent(params -> ReportPortal.emitLog(stepId, id -> {
SaveLogRQ logRq = new SaveLogRQ();
logRq.setLogTime(Calendar.getInstance().getTime());
logRq.setItemUuid(id);
logRq.setLevel(LogLevel.INFO.name());
logRq.setMessage("Parameters:\n\n" + ParameterUtils.formatParametersAsTable(params));
return logRq;
}));
.ifPresent(params ->
sendLog(stepId, "Parameters:\n\n" + formatParametersAsTable(params), LogLevel.INFO));
ofNullable(stepResult.getStep().getTable())
.ifPresent(table ->
sendLog(stepId, "Table:\n\n" + formatDataTable(table.getRows()), LogLevel.INFO));
}

/**
Expand Down Expand Up @@ -414,7 +415,7 @@ public void finishStep(StepResult stepResult) {
*/
public void sendStepResults(StepResult stepResult) {
Result result = stepResult.getResult();
String logLevel = getLogLevel(result.getStatus());
LogLevel logLevel = getLogLevel(result.getStatus());
Step step = stepResult.getStep();

if (step.getDocString() != null) {
Expand All @@ -434,47 +435,65 @@ public void sendStepResults(StepResult stepResult) {
* @param message log message to send
* @param level log level
*/
public void sendLog(final String message, final String level) {
public void sendLog(final String message, LogLevel level) {
ReportPortal.emitLog(itemId -> {
SaveLogRQ rq = new SaveLogRQ();
rq.setMessage(message);
rq.setItemUuid(itemId);
rq.setLevel(level);
rq.setLevel(level.name());
rq.setLogTime(Calendar.getInstance().getTime());
return rq;
});
}

/**
* Send step logs and/or execution results to ReportPortal
*
* @param itemId item ID future
* @param message log message to send
* @param level log level
*/
public void sendLog(Maybe<String> itemId, String message, LogLevel level) {
ReportPortal.emitLog(itemId, id -> {
SaveLogRQ rq = new SaveLogRQ();
rq.setMessage(message);
rq.setItemUuid(id);
rq.setLevel(level.name());
rq.setLogTime(Calendar.getInstance().getTime());
return rq;
});
}

private String getStepStatus(String status) {
private ItemStatus getStepStatus(String status) {
switch (status) {
case "failed":
return ItemStatusEnum.FAILED.toString();
return ItemStatus.FAILED;
case "passed":
return ItemStatusEnum.PASSED.toString();
return ItemStatus.PASSED;
case "skipped":
return ItemStatusEnum.SKIPPED.toString();
return ItemStatus.SKIPPED;
case "stopped":
return ItemStatusEnum.STOPPED.toString();
return ItemStatus.STOPPED;
case "interrupted":
return ItemStatusEnum.RESETED.toString();
return ItemStatus.INTERRUPTED;
case "cancelled":
return ItemStatusEnum.CANCELLED.toString();
return ItemStatus.CANCELLED;
default:
LOGGER.warn("Unknown step status received! Set it as SKIPPED");
return ItemStatusEnum.SKIPPED.toString();
return ItemStatus.SKIPPED;
}
}

private String getLogLevel(String status) {
private LogLevel getLogLevel(String status) {
switch (status) {
case "failed":
return ItemLogLevelEnum.ERROR.toString();
return LogLevel.ERROR;
case "stopped":
case "interrupted":
case "cancelled":
return ItemLogLevelEnum.WARN.toString();
return LogLevel.WARN;
default:
return ItemLogLevelEnum.INFO.toString();
return LogLevel.INFO;
}
}

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,6 @@ public void test_examples_parameters_for_steps() {
assertThat(logs.keySet(), hasSize(stepIdList.size()));
stepIdList.forEach(id -> assertThat(logs, hasKey(id)));
assertThat(logs.values().stream().map(SaveLogRQ::getMessage).collect(Collectors.toList()),
everyItem(startsWith("Parameters:")));
everyItem(startsWith("Parameters:\n\n")));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.epam.reportportal.karate.parameters;

import com.epam.reportportal.karate.utils.TestUtils;
import com.epam.reportportal.listeners.LogLevel;
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 com.epam.ta.reportportal.ws.model.log.SaveLogRQ;
import okhttp3.MultipartBody;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
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.hamcrest.Matchers.startsWith;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.*;

public class TableParametersTest {
private final String featureId = CommonUtils.namedId("feature_");
private final String scenarioId = CommonUtils.namedId("scenario_");
private final List<String> stepIds = Stream.generate(() -> CommonUtils.namedId("step_"))
.limit(4).collect(Collectors.toList());

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

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

@Test
@SuppressWarnings({"unchecked", "rawtypes"})
public void test_table_parameters_reporting() {
var results = TestUtils.runAsReport(rp, "classpath:feature/table.feature");
assertThat(results.getFailCount(), equalTo(0));

ArgumentCaptor<StartTestItemRQ> captor = ArgumentCaptor.forClass(StartTestItemRQ.class);
verify(client, times(1)).startTestItem(captor.capture());
verify(client, times(1)).startTestItem(same(featureId), captor.capture());
ArgumentCaptor<StartTestItemRQ> stepCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class);
verify(client, times(4)).startTestItem(same(scenarioId), stepCaptor.capture());
ArgumentCaptor<List> logCaptor = ArgumentCaptor.forClass(List.class);
verify(client, atLeastOnce()).log(logCaptor.capture());

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

Map<String, SaveLogRQ> logs = logCaptor
.getAllValues().
stream()
.flatMap(rq -> extractJsonParts((List<MultipartBody.Part>) rq).stream())
.filter(rq -> LogLevel.INFO.name().equals(rq.getLevel()))
.collect(Collectors.toMap(SaveLogRQ::getItemUuid, v -> v));
assertThat(logs.get(stepIds.get(2)).getMessage(), startsWith("Table:\n\n"));
}
}
9 changes: 9 additions & 0 deletions src/test/resources/feature/table.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Feature: test with parameter table
Scenario: Verify parameter table
Given def one = 'hello'
And def two = { baz: 'world' }
And table json
| foo | bar |
| one | { baz: 1 } |
| two.baz | ['baz', 'ban'] |
Then match json == [{ foo: 'hello', bar: { baz: 1 } }, { foo: 'world', bar: ['baz', 'ban'] }]

0 comments on commit e5bfcce

Please sign in to comment.