gitee.com/mirrors/gauge@v1.0.6/reporter/verboseColoredConsole.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 verboseColoredConsole struct {
    35  	writer               *goterminal.Writer
    36  	headingBuffer        bytes.Buffer
    37  	pluginMessagesBuffer bytes.Buffer
    38  	errorMessagesBuffer  bytes.Buffer
    39  	indentation          int
    40  }
    41  
    42  func newVerboseColoredConsole(out io.Writer) *verboseColoredConsole {
    43  	return &verboseColoredConsole{writer: goterminal.New(out)}
    44  }
    45  
    46  func (c *verboseColoredConsole) SuiteStart() {
    47  }
    48  
    49  func (c *verboseColoredConsole) SpecStart(spec *gauge.Specification, res result.Result) {
    50  	if res.(*result.SpecResult).Skipped {
    51  		return
    52  	}
    53  	msg := formatSpec(spec.Heading.Value)
    54  	logger.Info(false, msg)
    55  	c.displayMessage(msg+newline, ct.Cyan)
    56  	c.writer.Reset()
    57  }
    58  
    59  func (c *verboseColoredConsole) SpecEnd(spec *gauge.Specification, res result.Result) {
    60  	if res.(*result.SpecResult).Skipped {
    61  		return
    62  	}
    63  	printHookFailureVCC(c, res, res.GetPreHook)
    64  	printHookFailureVCC(c, res, res.GetPostHook)
    65  	c.displayMessage(newline, ct.None)
    66  	c.writer.Reset()
    67  }
    68  
    69  func (c *verboseColoredConsole) ScenarioStart(scenario *gauge.Scenario, i gauge_messages.ExecutionInfo, res result.Result) {
    70  	if res.(*result.ScenarioResult).ProtoScenario.ExecutionStatus == gauge_messages.ExecutionStatus_SKIPPED {
    71  		return
    72  	}
    73  	c.indentation += scenarioIndentation
    74  	msg := formatScenario(scenario.Heading.Value)
    75  	logger.Info(false, msg)
    76  
    77  	indentedText := indent(msg+"\t", c.indentation)
    78  	c.displayMessage(indentedText+newline, ct.Yellow)
    79  	c.writer.Reset()
    80  }
    81  
    82  func (c *verboseColoredConsole) ScenarioEnd(scenario *gauge.Scenario, res result.Result, i gauge_messages.ExecutionInfo) {
    83  	if res.(*result.ScenarioResult).ProtoScenario.ExecutionStatus == gauge_messages.ExecutionStatus_SKIPPED {
    84  		return
    85  	}
    86  	printHookFailureVCC(c, res, res.GetPreHook)
    87  	printHookFailureVCC(c, res, res.GetPostHook)
    88  
    89  	c.writer.Reset()
    90  	c.indentation -= scenarioIndentation
    91  }
    92  
    93  func (c *verboseColoredConsole) StepStart(stepText string) {
    94  	c.resetBuffers()
    95  	c.writer.Reset()
    96  
    97  	c.indentation += stepIndentation
    98  	logger.Debug(false, stepText)
    99  	c.headingBuffer.WriteString(indent(strings.TrimSpace(stepText), c.indentation))
   100  	c.displayMessage(c.headingBuffer.String()+newline, ct.None)
   101  }
   102  
   103  func (c *verboseColoredConsole) StepEnd(step gauge.Step, res result.Result, execInfo gauge_messages.ExecutionInfo) {
   104  	stepRes := res.(*result.StepResult)
   105  	c.writer.Clear()
   106  	if !(hookFailed(res.GetPreHook) || hookFailed(res.GetPostHook)) {
   107  		if stepRes.GetStepFailed() {
   108  			c.displayMessage(c.headingBuffer.String()+"\t ...[FAIL]\n", ct.Red)
   109  		} else {
   110  			c.displayMessage(c.headingBuffer.String()+"\t ...[PASS]\n", ct.Green)
   111  		}
   112  	} else {
   113  		c.displayMessage(c.headingBuffer.String()+newline, ct.None)
   114  	}
   115  	printHookFailureVCC(c, res, res.GetPreHook)
   116  	c.displayMessage(c.pluginMessagesBuffer.String(), ct.None)
   117  	c.displayMessage(c.errorMessagesBuffer.String(), ct.Red)
   118  	if stepRes.GetStepFailed() {
   119  		stepText := prepStepMsg(step.LineText)
   120  		logger.Error(false, stepText)
   121  		errMsg := prepErrorMessage(stepRes.ProtoStepExecResult().GetExecutionResult().GetErrorMessage())
   122  		logger.Error(false, errMsg)
   123  		specInfo := prepSpecInfo(execInfo.GetCurrentSpec().GetFileName(), step.LineNo, step.InConcept())
   124  		logger.Error(false, specInfo)
   125  		stacktrace := prepStacktrace(stepRes.ProtoStepExecResult().GetExecutionResult().GetStackTrace())
   126  		logger.Error(false, stacktrace)
   127  
   128  		msg := formatErrorFragment(stepText, c.indentation) + formatErrorFragment(specInfo, c.indentation) + formatErrorFragment(errMsg, c.indentation) + formatErrorFragment(stacktrace, c.indentation)
   129  
   130  		c.displayMessage(msg, ct.Red)
   131  	}
   132  	printHookFailureVCC(c, res, res.GetPostHook)
   133  	c.indentation -= stepIndentation
   134  	c.writer.Reset()
   135  	c.resetBuffers()
   136  }
   137  
   138  func (c *verboseColoredConsole) ConceptStart(conceptHeading string) {
   139  	c.indentation += stepIndentation
   140  	logger.Debug(false, conceptHeading)
   141  	c.displayMessage(indent(strings.TrimSpace(conceptHeading), c.indentation)+newline, ct.Magenta)
   142  	c.writer.Reset()
   143  }
   144  
   145  func (c *verboseColoredConsole) ConceptEnd(res result.Result) {
   146  	c.indentation -= stepIndentation
   147  }
   148  
   149  func (c *verboseColoredConsole) SuiteEnd(res result.Result) {
   150  	suiteRes := res.(*result.SuiteResult)
   151  	printHookFailureVCC(c, res, res.GetPreHook)
   152  	printHookFailureVCC(c, res, res.GetPostHook)
   153  	for _, e := range suiteRes.UnhandledErrors {
   154  		logger.Error(false, e.Error())
   155  		c.displayMessage(indent(e.Error(), c.indentation+errorIndentation)+newline, ct.Red)
   156  	}
   157  }
   158  
   159  func (c *verboseColoredConsole) DataTable(table string) {
   160  	logger.Debug(false, table)
   161  	c.displayMessage(table, ct.Yellow)
   162  	c.writer.Reset()
   163  }
   164  
   165  func (c *verboseColoredConsole) Errorf(text string, args ...interface{}) {
   166  	msg := fmt.Sprintf(text, args...)
   167  	logger.Error(false, msg)
   168  	msg = indent(msg, c.indentation+errorIndentation) + newline
   169  	c.displayMessage(msg, ct.Red)
   170  	c.errorMessagesBuffer.WriteString(msg)
   171  }
   172  
   173  // Write writes the bytes to console via goterminal's writer.
   174  // This is called when any sysouts are to be printed on console.
   175  func (c *verboseColoredConsole) Write(b []byte) (int, error) {
   176  	text := string(b)
   177  	c.pluginMessagesBuffer.WriteString(text)
   178  	c.displayMessage(text, ct.None)
   179  	return len(b), nil
   180  }
   181  
   182  func (c *verboseColoredConsole) displayMessage(msg string, color ct.Color) {
   183  	ct.Foreground(color, false)
   184  	defer ct.ResetColor()
   185  	fmt.Fprint(c.writer, msg)
   186  	c.writer.Print()
   187  }
   188  
   189  func (c *verboseColoredConsole) resetBuffers() {
   190  	c.headingBuffer.Reset()
   191  	c.pluginMessagesBuffer.Reset()
   192  	c.errorMessagesBuffer.Reset()
   193  }
   194  
   195  func printHookFailureVCC(c *verboseColoredConsole, res result.Result, hookFailure func() []*gauge_messages.ProtoHookFailure) bool {
   196  	if hookFailed(hookFailure) {
   197  		errMsg := prepErrorMessage(hookFailure()[0].GetErrorMessage())
   198  		logger.Error(false, errMsg)
   199  		stacktrace := prepStacktrace(hookFailure()[0].GetStackTrace())
   200  		logger.Error(false, stacktrace)
   201  		c.displayMessage(formatErrorFragment(errMsg, c.indentation)+formatErrorFragment(stacktrace, c.indentation), ct.Red)
   202  		return false
   203  	}
   204  	return true
   205  }
   206  
   207  func hookFailed(hookFailure func() []*gauge_messages.ProtoHookFailure) bool {
   208  	return len(hookFailure()) > 0
   209  }