github.com/getgauge/gauge@v1.6.9/execution/merge.go (about) 1 /*---------------------------------------------------------------- 2 * Copyright (c) ThoughtWorks, Inc. 3 * Licensed under the Apache License, Version 2.0 4 * See LICENSE in the project root for license information. 5 *----------------------------------------------------------------*/ 6 7 package execution 8 9 import ( 10 "time" 11 12 "strings" 13 14 m "github.com/getgauge/gauge-proto/go/gauge_messages" 15 "github.com/getgauge/gauge/execution/result" 16 ) 17 18 func mergeDataTableSpecResults(sResult *result.SuiteResult) *result.SuiteResult { 19 suiteRes := result.NewSuiteResult(sResult.Tags, time.Now()) 20 suiteRes.IsFailed = sResult.IsFailed 21 suiteRes.ExecutionTime = sResult.ExecutionTime 22 suiteRes.PostSuite = sResult.PostSuite 23 suiteRes.PreSuite = sResult.PreSuite 24 suiteRes.UnhandledErrors = sResult.UnhandledErrors 25 suiteRes.Timestamp = sResult.Timestamp 26 suiteRes.ProjectName = sResult.ProjectName 27 suiteRes.Environment = sResult.Environment 28 suiteRes.Tags = sResult.Tags 29 suiteRes.PreHookMessages = append(suiteRes.PreHookMessages, sResult.PreHookMessages...) 30 suiteRes.PostHookMessages = append(suiteRes.PostHookMessages, sResult.PostHookMessages...) 31 suiteRes.PreHookScreenshotFiles = append(suiteRes.PreHookScreenshotFiles, sResult.PreHookScreenshotFiles...) 32 suiteRes.PostHookScreenshotFiles = append(suiteRes.PostHookScreenshotFiles, sResult.PostHookScreenshotFiles...) 33 suiteRes.PreHookScreenshots = append(suiteRes.PreHookScreenshots, sResult.PreHookScreenshots...) 34 suiteRes.PostHookScreenshots = append(suiteRes.PostHookScreenshots, sResult.PostHookScreenshots...) 35 combinedResults := make(map[string][]*result.SpecResult) 36 for _, res := range sResult.SpecResults { 37 fileName := res.ProtoSpec.GetFileName() 38 combinedResults[fileName] = append(combinedResults[fileName], res) 39 } 40 for _, res := range combinedResults { 41 mergedRes := res[0] 42 if len(res) > 1 { 43 mergedRes = mergeResults(res) 44 } 45 if mergedRes.GetFailed() { 46 suiteRes.SpecsFailedCount++ 47 } else if mergedRes.Skipped { 48 suiteRes.SpecsSkippedCount++ 49 } 50 suiteRes.SpecResults = append(suiteRes.SpecResults, mergedRes) 51 } 52 return suiteRes 53 } 54 55 func hasTableDrivenSpec(results []*result.SpecResult) bool { 56 for _, r := range results { 57 if r.ProtoSpec.GetIsTableDriven() { 58 return true 59 } 60 } 61 return false 62 } 63 64 func mergeResults(results []*result.SpecResult) *result.SpecResult { 65 specResult := &result.SpecResult{ProtoSpec: &m.ProtoSpec{ 66 IsTableDriven: hasTableDrivenSpec(results), 67 PreHookMessages: results[0].ProtoSpec.PreHookMessages, 68 PostHookMessages: results[len(results)-1].ProtoSpec.PostHookMessages, 69 }} 70 var scnResults []*m.ProtoItem 71 table := &m.ProtoTable{} 72 dataTableScnResults := make(map[string][]*m.ProtoTableDrivenScenario) 73 includedTableRowIndexMap := make(map[int32]bool) 74 max := results[0].ExecutionTime 75 for _, res := range results { 76 specResult.ExecutionTime += res.ExecutionTime 77 specResult.Errors = res.Errors 78 if res.ExecutionTime > max { 79 max = res.ExecutionTime 80 } 81 if res.GetFailed() { 82 specResult.IsFailed = true 83 } 84 85 var tableRows []*m.ProtoTableRow // nolint 86 87 for _, item := range res.ProtoSpec.Items { 88 switch item.ItemType { 89 case m.ProtoItem_Scenario: 90 scnResults = append(scnResults, item) 91 modifySpecStats(item.Scenario, specResult) 92 case m.ProtoItem_TableDrivenScenario: 93 tableRowIndex := item.TableDrivenScenario.TableRowIndex 94 if _, ok := includedTableRowIndexMap[tableRowIndex]; !ok { 95 table.Rows = append(table.Rows, tableRows...) 96 includedTableRowIndexMap[tableRowIndex] = true 97 } 98 item.TableDrivenScenario.TableRowIndex = int32(len(table.Rows) - 1) 99 scnResults = append(scnResults, item) 100 heading := item.TableDrivenScenario.Scenario.ScenarioHeading 101 dataTableScnResults[heading] = append(dataTableScnResults[heading], item.TableDrivenScenario) 102 case m.ProtoItem_Table: 103 table.Headers = item.Table.Headers 104 tableRows = item.Table.GetRows() 105 if len(res.GetPreHook()) > 0 { 106 table.Rows = append(table.Rows, tableRows...) 107 } 108 } 109 } 110 addHookFailure(table, res.GetPreHook(), specResult.AddPreHook) 111 addHookFailure(table, res.GetPostHook(), specResult.AddPostHook) 112 } 113 if InParallel { 114 specResult.ExecutionTime = max 115 } 116 aggregateDataTableScnStats(dataTableScnResults, specResult) 117 specResult.ProtoSpec.FileName = results[0].ProtoSpec.FileName 118 specResult.ProtoSpec.Tags = results[0].ProtoSpec.Tags 119 specResult.ProtoSpec.SpecHeading = results[0].ProtoSpec.SpecHeading 120 specResult.ProtoSpec.Items = getItems(table, scnResults, results) 121 return specResult 122 } 123 124 func addHookFailure(table *m.ProtoTable, f []*m.ProtoHookFailure, add func(...*m.ProtoHookFailure)) { 125 for _, h := range f { 126 h.TableRowIndex = int32(len(table.Rows) - 1) 127 } 128 add(f...) 129 } 130 131 func getItems(table *m.ProtoTable, scnResults []*m.ProtoItem, results []*result.SpecResult) (items []*m.ProtoItem) { 132 index := 0 133 for _, item := range results[0].ProtoSpec.Items { 134 switch item.ItemType { 135 case m.ProtoItem_Scenario, m.ProtoItem_TableDrivenScenario: 136 items = append(items, scnResults[index]) 137 index++ 138 case m.ProtoItem_Table: 139 items = append(items, &m.ProtoItem{ItemType: m.ProtoItem_Table, Table: table}) 140 default: 141 items = append(items, item) 142 } 143 } 144 items = append(items, scnResults[index:]...) 145 return 146 } 147 148 func aggregateDataTableScnStats(results map[string][]*m.ProtoTableDrivenScenario, specResult *result.SpecResult) { 149 for _, dResult := range results { 150 for _, res := range dResult { 151 isTableIndicesExcluded := false 152 if res.Scenario.ExecutionStatus == m.ExecutionStatus_FAILED { 153 specResult.ScenarioFailedCount++ 154 } else if res.Scenario.ExecutionStatus == m.ExecutionStatus_SKIPPED && 155 !strings.Contains(res.Scenario.SkipErrors[0], "--table-rows") { 156 specResult.ScenarioSkippedCount++ 157 specResult.Skipped = true 158 } else if res.Scenario.ExecutionStatus == m.ExecutionStatus_SKIPPED && 159 strings.Contains(res.Scenario.SkipErrors[0], "--table-rows") { 160 isTableIndicesExcluded = true 161 } 162 if !isTableIndicesExcluded { 163 specResult.ScenarioCount++ 164 } 165 } 166 } 167 } 168 169 func modifySpecStats(scn *m.ProtoScenario, specRes *result.SpecResult) { 170 switch scn.ExecutionStatus { 171 case m.ExecutionStatus_SKIPPED: 172 specRes.ScenarioSkippedCount++ 173 case m.ExecutionStatus_FAILED: 174 specRes.ScenarioFailedCount++ 175 } 176 specRes.ScenarioCount++ 177 }