Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
fix(server): save campaign - scenario link at scenario execution end
Browse files Browse the repository at this point in the history
  • Loading branch information
rbenyoussef committed May 12, 2023
1 parent 0e15566 commit b6f4e5f
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.chutneytesting.server.core.domain.dataset.DataSetHistoryRepository;
import com.chutneytesting.server.core.domain.execution.ExecutionRequest;
import com.chutneytesting.server.core.domain.execution.ScenarioExecutionEngine;
import com.chutneytesting.server.core.domain.execution.ScenarioExecutionEngineAsync;
import com.chutneytesting.server.core.domain.execution.history.ExecutionHistory;
import com.chutneytesting.server.core.domain.execution.history.ExecutionHistoryRepository;
import com.chutneytesting.server.core.domain.execution.history.ImmutableExecutionHistory;
Expand All @@ -29,6 +30,7 @@
import com.chutneytesting.server.core.domain.scenario.TestCaseMetadataImpl;
import com.chutneytesting.server.core.domain.scenario.campaign.Campaign;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.reactivex.Observable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
Expand All @@ -48,6 +50,7 @@ public class CampaignExecutionEngineTest {

private final CampaignRepository campaignRepository = mock(CampaignRepository.class);
private final ScenarioExecutionEngine scenarioExecutionEngine = mock(ScenarioExecutionEngine.class);
private final ScenarioExecutionEngineAsync scenarioExecutionEngineAsync = mock(ScenarioExecutionEngineAsync.class);
private final ExecutionHistoryRepository executionHistoryRepository = mock(ExecutionHistoryRepository.class);
private final TestCaseRepositoryAggregator testCaseRepository = mock(TestCaseRepositoryAggregator.class);
private final DataSetHistoryRepository dataSetHistoryRepository = mock(DataSetHistoryRepository.class);
Expand Down Expand Up @@ -78,7 +81,8 @@ public void should_override_scenario_dataset_with_campaign_dataset_before_execut

when(campaignRepository.findById(campaign.id)).thenReturn(campaign);
when(testCaseRepository.findExecutableById(composedTestCase.id())).thenReturn(of(composedTestCase));
when(scenarioExecutionEngine.execute(any(ExecutionRequest.class), any())).thenReturn(mock(ScenarioExecutionReport.class));
when(scenarioExecutionEngineAsync.followExecution(any(), any())).thenReturn(mock(Observable.class));
when(scenarioExecutionEngineAsync.followExecution(any(), any()).blockingLast()).thenReturn(mock(ScenarioExecutionReport.class));
when(executionHistoryRepository.getExecution(any(), any())).thenReturn(executionWithId(42L));

// When
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ public ScenarioExecutionEngine(ServerTestEngine executionEngine,
* @param executionRequest The request execution.
* @return an execution Report.
*/
public ScenarioExecutionReport execute(ExecutionRequest executionRequest, Optional<Pair<String, Integer>> executionDataset) throws ScenarioNotFoundException, ScenarioNotParsableException {
return executionEngineAsync.followExecution(executionRequest.testCase.id(), executionEngineAsync.execute(executionRequest, executionDataset)).blockingLast();
public Long execute(ExecutionRequest executionRequest, Optional<Pair<String, Integer>> executionDataset) throws ScenarioNotFoundException, ScenarioNotParsableException {
return executionEngineAsync.execute(executionRequest, executionDataset);
}

public ScenarioExecutionReport followExecution(String scenarioId, Long scenarioExecutionId) throws ScenarioNotFoundException, ScenarioNotParsableException {
return executionEngineAsync.followExecution(scenarioId, scenarioExecutionId).blockingLast();
}

public ScenarioExecutionReport simpleSyncExecution(ExecutionRequest executionRequest) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ private void addCurrentExecution(List<CampaignExecutionReport> currentCampaignEx
if (currentCampaignExecutionReports == null) {
currentCampaignExecutionReports = new ArrayList<>();
}
currentCampaignExecutionReports.add(0, campaignExecutionReport);
if(!currentCampaignExecutionReports.contains(campaignExecutionReport))
currentCampaignExecutionReports.add(0, campaignExecutionReport);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

/**
* Right-side port for secondary actors of the business domain. See {@link CampaignExecutionEngine}
*
* <p>
* Use to Store Campaign
*/
public interface CampaignRepository {
Expand All @@ -16,6 +16,8 @@ public interface CampaignRepository {

void saveReport(Long campaignId, CampaignExecutionReport report);

void updateCampaignExecutionScenario(Long campaignExecutionId, String scenarioId, Long scenarioExecutionId);

boolean removeById(Long id);

Campaign findById(Long campaignId) throws CampaignNotFoundException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,20 @@ private int saveScenarioExecutionReport(Long campaignId, Long campaignExecutionI
return uiNamedParameterJdbcTemplate.update(QUERY_SAVE_CAMPAIGN_EXECUTION_HISTORY, parameters);
}

private static final String QUERY_UPDATE_CAMPAIGN_EXECUTION_SCENARIO =
"UPDATE CAMPAIGN_EXECUTION_HISTORY SET " +
"SCENARIO_EXECUTION_ID = :idScenarioExecution " +
"WHERE ID = :idCampaignExecution AND " +
"SCENARIO_ID = :idScenario";

int updateCampaignExecutionScenario(Long campaignExecutionId, String scenarioId, Long scenarioExecutionId) {
HashMap<String, Object> parameters = Maps.newHashMap();
parameters.put("idCampaignExecution", campaignExecutionId);
parameters.put("idScenario", scenarioId);
parameters.put("idScenarioExecution", scenarioExecutionId);
return uiNamedParameterJdbcTemplate.update(QUERY_UPDATE_CAMPAIGN_EXECUTION_SCENARIO, parameters);
}

Long generateCampaignExecutionId() {
return uiNamedParameterJdbcTemplate.queryForObject("SELECT nextval('CAMPAIGN_EXECUTION_SEQ')", emptyMap(), Long.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public void saveReport(Long campaignId, CampaignExecutionReport report) {
campaignExecutionRepository.saveCampaignReport(campaignId, report);
}

@Override
public void updateCampaignExecutionScenario(Long campaignExecutionId, String scenarioId, Long scenarioExecutionId) {
campaignExecutionRepository.updateCampaignExecutionScenario(campaignExecutionId, scenarioId, scenarioExecutionId);
}

/**
* Remove a campaign from its id.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,6 @@ public CampaignExecutionReport executeScenarioInCampaign(List<String> failedIds,
currentCampaignExecutionsStopRequests.remove(executionId);
currentCampaignExecutions.remove(campaign.id);

Try.exec(() -> {
campaignRepository.saveReport(campaign.id, campaignExecutionReport);
return null;
}).ifFailed(e -> LOGGER.error("Error saving report of campaign {} execution {}", campaign.id, campaignExecutionReport.executionId));

Try.exec(() -> {
metrics.onCampaignExecutionEnded(campaign, campaignExecutionReport);
return null;
Expand All @@ -172,6 +167,10 @@ private CampaignExecutionReport execute(Campaign campaign, CampaignExecutionRepo
.collect(Collectors.toList());

campaignExecutionReport.initExecution(testCases, campaign.executionEnvironment(), campaignExecutionReport.userId);
Try.exec(() -> {
campaignRepository.saveReport(campaign.id, campaignExecutionReport);
return null;
}).ifFailed(e -> LOGGER.error("Error saving initial report of campaign {} execution {}", campaign.id, campaignExecutionReport.executionId));
try {
if (campaign.parallelRun) {
Collection<Callable<Object>> toExecute = Lists.newArrayList();
Expand Down Expand Up @@ -199,10 +198,10 @@ private Consumer<TestCase> executeScenarioInCampaign(Campaign campaign, Campaign
// Init scenario execution in campaign report
campaignExecutionReport.startScenarioExecution(testCase, campaign.executionEnvironment(), campaignExecutionReport.userId);
// Execute scenario
ScenarioExecutionReportCampaign scenarioExecutionReport = executeScenario(campaign, testCase, campaignExecutionReport.userId);
ScenarioExecutionReportCampaign scenarioExecutionReport = executeScenario(campaign, testCase, campaignExecutionReport);
// Retry one time if failed
if (campaign.retryAuto && ServerReportStatus.FAILURE.equals(scenarioExecutionReport.status())) {
scenarioExecutionReport = executeScenario(campaign, testCase, campaignExecutionReport.userId);
scenarioExecutionReport = executeScenario(campaign, testCase, campaignExecutionReport);
}
// Add scenario report to campaign's one
Optional.ofNullable(scenarioExecutionReport)
Expand All @@ -216,13 +215,15 @@ private Consumer<TestCase> executeScenarioInCampaign(Campaign campaign, Campaign
};
}

private ScenarioExecutionReportCampaign executeScenario(Campaign campaign, TestCase testCase, String userId) {
private ScenarioExecutionReportCampaign executeScenario(Campaign campaign, TestCase testCase, CampaignExecutionReport campaignExecutionReport) {
Long executionId;
String scenarioName;
try {
LOGGER.trace("Execute scenario {} for campaign {}", testCase.id(), campaign.id);
ExecutionRequest executionRequest = buildExecutionRequest(campaign, testCase, userId);
ScenarioExecutionReport scenarioExecutionReport = scenarioExecutionEngine.execute(executionRequest, Optional.empty()); // todo
ExecutionRequest executionRequest = buildExecutionRequest(campaign, testCase, campaignExecutionReport.userId);
Long scenarioExecutionId = scenarioExecutionEngine.execute(executionRequest, Optional.empty());
updateCampaignExecutionScenario(campaignExecutionReport.executionId, testCase.id(), scenarioExecutionId);
ScenarioExecutionReport scenarioExecutionReport = scenarioExecutionEngine.followExecution(executionRequest.testCase.id(), scenarioExecutionId);
executionId = scenarioExecutionReport.executionId;
scenarioName = scenarioExecutionReport.scenarioName;
} catch (FailedExecutionAttempt e) {
Expand Down Expand Up @@ -277,4 +278,11 @@ private Campaign selectExecutionEnvironment(Campaign campaign, String environmen
Optional.ofNullable(environment).ifPresent(campaign::executionEnvironment);
return campaign;
}

private void updateCampaignExecutionScenario(Long campaignExecutionId, String scenarioId, Long scenarioExecutionId) {
Try.exec(() -> {
campaignRepository.updateCampaignExecutionScenario(campaignExecutionId, scenarioId, scenarioExecutionId);
return null;
}).ifFailed(e -> LOGGER.error("Error updating campaign scenario execution link of campaignExecution {} scenario {}", campaignExecutionId, scenarioId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ public void saveReport(Long campaignId, CampaignExecutionReport report) {

}

@Override
public void updateCampaignExecutionScenario(Long campaignExecutionId, String scenarioId, Long scenarioExecutionId) {
throw new NotImplementedException();
}

@Override
public boolean removeById(Long id) {
return campaignsById.remove(id) != null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void setUp() {
public void should_update_jira_xray() {
// Given
Campaign campaign = createCampaign(firstTestCase, secondTestCase);
when(scenarioExecutionEngine.execute(any(ExecutionRequest.class), any())).thenReturn(mock(ScenarioExecutionReport.class));
when(scenarioExecutionEngine.followExecution(any(), any())).thenReturn(mock(ScenarioExecutionReport.class));

// When
CampaignExecutionReport cer = sut.executeScenarioInCampaign(emptyList(), campaign, "user");
Expand All @@ -127,7 +127,7 @@ public void should_execute_scenarios_in_sequence_and_store_reports_in_campaign_r
// Given
Campaign campaign = createCampaign(firstTestCase, secondTestCase);

when(scenarioExecutionEngine.execute(any(ExecutionRequest.class), any())).thenReturn(mock(ScenarioExecutionReport.class));
when(scenarioExecutionEngine.followExecution(any(), anyLong())).thenReturn(mock(ScenarioExecutionReport.class));

// When
CampaignExecutionReport campaignExecutionReport = sut.executeScenarioInCampaign(emptyList(), campaign, "user");
Expand All @@ -148,12 +148,28 @@ public void should_execute_scenarios_in_sequence_and_store_reports_in_campaign_r
);
}

@Test
public void should_retrieve_campaign_scenario_execution_link_when_running() {
// Given
Campaign campaign = createCampaign(firstTestCase, secondTestCase);

when(scenarioExecutionEngine.followExecution(any(), anyLong())).thenReturn(mock(ScenarioExecutionReport.class));

// When
CampaignExecutionReport campaignExecutionReport = sut.executeScenarioInCampaign(emptyList(), campaign, "user");

// Then
verify(campaignRepository).saveReport(campaign.id, campaignExecutionReport);
verify(campaignRepository).updateCampaignExecutionScenario(eq(campaignExecutionReport.executionId), eq(firstTestCase.id()), anyLong());
verify(campaignRepository).updateCampaignExecutionScenario(eq(campaignExecutionReport.executionId), eq(secondTestCase.id()), anyLong());
}

@Test
public void should_execute_partially_scenarios_requested() {
// Given
Campaign campaign = createCampaign(createGwtTestCase("not executed test case"), secondTestCase);

when(scenarioExecutionEngine.execute(any(ExecutionRequest.class), any())).thenReturn(mock(ScenarioExecutionReport.class));
when(scenarioExecutionEngine.followExecution(any(), any())).thenReturn(mock(ScenarioExecutionReport.class));

// When
CampaignExecutionReport campaignExecutionReport = sut.executeScenarioInCampaign(singletonList("2"), campaign, "user");
Expand All @@ -174,10 +190,11 @@ public void should_stop_execution_of_scenarios_when_requested() {
// Given
Campaign campaign = createCampaign(firstTestCase, secondTestCase);

when(scenarioExecutionEngine.execute(any(ExecutionRequest.class), any())).then((Answer<ScenarioExecutionReport>) invocationOnMock -> {
when(scenarioExecutionEngine.execute(any(), any())).then((Answer<?>) invocationOnMock -> {
awaitDuring(1, SECONDS);
return mock(ScenarioExecutionReport.class);
return anyLong();
});
when(scenarioExecutionEngine.followExecution(any(), any())).thenReturn(mock(ScenarioExecutionReport.class));

Long firstScenarioExecutionId = 10L;
when(executionHistoryRepository.getExecution(eq(firstTestCase.id()), or(eq(0L), eq(10L))))
Expand Down Expand Up @@ -210,7 +227,7 @@ public void should_retry_failed_scenario() {
// Given
Campaign campaign = createCampaign(firstTestCase, secondTestCase, true);

when(scenarioExecutionEngine.execute(any(ExecutionRequest.class), any())).thenReturn(mock(ScenarioExecutionReport.class));
when(scenarioExecutionEngine.followExecution(any(), any())).thenReturn(mock(ScenarioExecutionReport.class));
when(executionHistoryRepository.getExecution(eq(firstTestCase.id()), or(eq(0L), eq(10L)))).thenReturn(failedExecutionWithId(10L));
when(executionHistoryRepository.getExecution(eq(secondTestCase.id()), or(eq(0L), eq(20L)))).thenReturn(failedExecutionWithId(20L));

Expand All @@ -226,10 +243,11 @@ public void should_execute_scenario_in_parallel() {
// Given
Campaign campaign = createCampaign(firstTestCase, secondTestCase, true, false);

when(scenarioExecutionEngine.execute(any(ExecutionRequest.class), any())).then((Answer<ScenarioExecutionReport>) invocationOnMock -> {
when(scenarioExecutionEngine.execute(any(), any())).then((Answer<?>) invocationOnMock -> {
awaitDuring(1, SECONDS);
return mock(ScenarioExecutionReport.class);
return anyLong();
});
when(scenarioExecutionEngine.followExecution(any(), any())).thenReturn(mock(ScenarioExecutionReport.class));
when(executionHistoryRepository.getExecution(eq(firstTestCase.id()), or(eq(0L), eq(10L)))).thenReturn(failedExecutionWithId(10L));
when(executionHistoryRepository.getExecution(eq(secondTestCase.id()), or(eq(0L), eq(20L)))).thenReturn(failedExecutionWithId(20L));

Expand Down Expand Up @@ -362,7 +380,7 @@ public void should_override_scenario_dataset_with_campaign_dataset_before_execut

when(campaignRepository.findById(campaign.id)).thenReturn(campaign);
when(testCaseRepository.findExecutableById(gwtTestCase.id())).thenReturn(of(gwtTestCase));
when(scenarioExecutionEngine.execute(any(ExecutionRequest.class), any())).thenReturn(mock(ScenarioExecutionReport.class));
when(scenarioExecutionEngine.followExecution(any(), any())).thenReturn(mock(ScenarioExecutionReport.class));
when(executionHistoryRepository.getExecution(any(), any())).thenReturn(executionWithId(42L));

// When
Expand Down

0 comments on commit b6f4e5f

Please sign in to comment.