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  }