gitee.com/mirrors/gauge@v1.0.6/reporter/coloredConsole.go (about) 1 // Copyright 2015 ThoughtWorks, Inc. 2 3 // This file is part of Gauge. 4 5 // Gauge is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 10 // Gauge is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 15 // You should have received a copy of the GNU General Public License 16 // along with Gauge. If not, see <http://www.gnu.org/licenses/>. 17 18 package reporter 19 20 import ( 21 "bytes" 22 "fmt" 23 "io" 24 "strings" 25 26 "github.com/apoorvam/goterminal" 27 ct "github.com/daviddengcn/go-colortext" 28 "github.com/getgauge/gauge/execution/result" 29 "github.com/getgauge/gauge/gauge" 30 "github.com/getgauge/gauge/gauge_messages" 31 "github.com/getgauge/gauge/logger" 32 ) 33 34 type coloredConsole struct { 35 writer *goterminal.Writer 36 indentation int 37 sceFailuresBuf bytes.Buffer 38 } 39 40 func newColoredConsole(out io.Writer) *coloredConsole { 41 return &coloredConsole{writer: goterminal.New(out)} 42 } 43 44 func (c *coloredConsole) SuiteStart() { 45 } 46 47 func (c *coloredConsole) SpecStart(spec *gauge.Specification, res result.Result) { 48 if res.(*result.SpecResult).Skipped { 49 return 50 } 51 msg := formatSpec(spec.Heading.Value) 52 logger.Info(false, msg) 53 c.displayMessage(msg+newline, ct.Cyan) 54 c.writer.Reset() 55 } 56 57 func (c *coloredConsole) SpecEnd(spec *gauge.Specification, res result.Result) { 58 if res.(*result.SpecResult).Skipped { 59 return 60 } 61 printHookFailureCC(c, res, res.GetPreHook) 62 printHookFailureCC(c, res, res.GetPostHook) 63 c.displayMessage(newline, ct.None) 64 c.writer.Reset() 65 } 66 67 func (c *coloredConsole) ScenarioStart(scenario *gauge.Scenario, i gauge_messages.ExecutionInfo, res result.Result) { 68 if res.(*result.ScenarioResult).ProtoScenario.ExecutionStatus == gauge_messages.ExecutionStatus_SKIPPED { 69 return 70 } 71 c.indentation += scenarioIndentation 72 msg := formatScenario(scenario.Heading.Value) 73 logger.Info(false, msg) 74 75 indentedText := indent(msg+"\t", c.indentation) 76 c.displayMessage(indentedText, ct.Yellow) 77 } 78 79 func (c *coloredConsole) ScenarioEnd(scenario *gauge.Scenario, res result.Result, i gauge_messages.ExecutionInfo) { 80 if res.(*result.ScenarioResult).ProtoScenario.ExecutionStatus == gauge_messages.ExecutionStatus_SKIPPED { 81 return 82 } 83 if printHookFailureCC(c, res, res.GetPreHook) { 84 if c.sceFailuresBuf.Len() != 0 { 85 c.displayMessage(newline+strings.Trim(c.sceFailuresBuf.String(), newline)+newline, ct.Red) 86 } else { 87 c.displayMessage(newline, ct.None) 88 } 89 } 90 91 printHookFailureCC(c, res, res.GetPostHook) 92 c.indentation -= scenarioIndentation 93 c.writer.Reset() 94 c.sceFailuresBuf.Reset() 95 } 96 97 func (c *coloredConsole) StepStart(stepText string) { 98 c.indentation += stepIndentation 99 logger.Debug(false, stepText) 100 } 101 102 func (c *coloredConsole) StepEnd(step gauge.Step, res result.Result, execInfo gauge_messages.ExecutionInfo) { 103 stepRes := res.(*result.StepResult) 104 if !(hookFailed(res.GetPreHook) || hookFailed(res.GetPostHook)) { 105 if stepRes.GetStepFailed() { 106 c.displayMessage(getFailureSymbol(), ct.Red) 107 } else { 108 c.displayMessage(getSuccessSymbol(), ct.Green) 109 } 110 } 111 if printHookFailureCC(c, res, res.GetPreHook) && stepRes.GetStepFailed() { 112 stepText := strings.TrimLeft(prepStepMsg(step.LineText), newline) 113 logger.Error(false, stepText) 114 errMsg := prepErrorMessage(stepRes.ProtoStepExecResult().GetExecutionResult().GetErrorMessage()) 115 logger.Error(false, errMsg) 116 specInfo := prepSpecInfo(execInfo.GetCurrentSpec().GetFileName(), step.LineNo, step.InConcept()) 117 logger.Error(false, specInfo) 118 stacktrace := prepStacktrace(stepRes.ProtoStepExecResult().GetExecutionResult().GetStackTrace()) 119 logger.Error(false, stacktrace) 120 121 failureMsg := formatErrorFragment(stepText, c.indentation) + formatErrorFragment(specInfo, c.indentation) + formatErrorFragment(errMsg, c.indentation) + formatErrorFragment(stacktrace, c.indentation) 122 c.sceFailuresBuf.WriteString(failureMsg) 123 } 124 printHookFailureCC(c, res, res.GetPostHook) 125 c.indentation -= stepIndentation 126 } 127 128 func (c *coloredConsole) ConceptStart(conceptHeading string) { 129 c.indentation += stepIndentation 130 logger.Debug(false, conceptHeading) 131 } 132 133 func (c *coloredConsole) ConceptEnd(res result.Result) { 134 c.indentation -= stepIndentation 135 } 136 137 func (c *coloredConsole) SuiteEnd(res result.Result) { 138 suiteRes := res.(*result.SuiteResult) 139 printHookFailureCC(c, res, res.GetPreHook) 140 printHookFailureCC(c, res, res.GetPostHook) 141 for _, e := range suiteRes.UnhandledErrors { 142 logger.Error(false, e.Error()) 143 c.displayMessage(indent(e.Error(), c.indentation+errorIndentation)+newline, ct.Red) 144 } 145 } 146 147 func (c *coloredConsole) DataTable(table string) { 148 logger.Debug(false, table) 149 c.displayMessage(table, ct.Yellow) 150 c.writer.Reset() 151 } 152 153 func (c *coloredConsole) Errorf(text string, args ...interface{}) { 154 msg := fmt.Sprintf(text, args...) 155 logger.Error(false, msg) 156 msg = indent(msg, c.indentation+errorIndentation) + newline 157 c.displayMessage(msg, ct.Red) 158 } 159 160 // Write writes the bytes to console via goterminal's writer. 161 // This is called when any sysouts are to be printed on console. 162 func (c *coloredConsole) Write(b []byte) (int, error) { 163 text := string(b) 164 c.displayMessage(text, ct.None) 165 return len(b), nil 166 } 167 168 func (c *coloredConsole) displayMessage(msg string, color ct.Color) { 169 ct.Foreground(color, false) 170 defer ct.ResetColor() 171 fmt.Fprint(c.writer, msg) 172 c.writer.Print() 173 } 174 175 func printHookFailureCC(c *coloredConsole, res result.Result, hookFailure func() []*gauge_messages.ProtoHookFailure) bool { 176 if len(hookFailure()) > 0 { 177 errMsg := prepErrorMessage(hookFailure()[0].GetErrorMessage()) 178 logger.Error(false, errMsg) 179 stacktrace := prepStacktrace(hookFailure()[0].GetStackTrace()) 180 logger.Error(false, stacktrace) 181 c.displayMessage(newline+formatErrorFragment(errMsg, c.indentation)+formatErrorFragment(stacktrace, c.indentation), ct.Red) 182 return false 183 } 184 return true 185 }