github.com/getgauge/gauge@v1.6.9/validation/validation_test.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 validation
     8  
     9  import (
    10  	"net"
    11  	"testing"
    12  
    13  	"github.com/getgauge/gauge-proto/go/gauge_messages"
    14  	"github.com/getgauge/gauge/gauge"
    15  	"github.com/getgauge/gauge/parser"
    16  	"github.com/getgauge/gauge/runner"
    17  
    18  	"errors"
    19  
    20  	"bytes"
    21  
    22  	. "gopkg.in/check.v1"
    23  )
    24  
    25  func Test(t *testing.T) { TestingT(t) }
    26  
    27  type MySuite struct{}
    28  
    29  var _ = Suite(&MySuite{})
    30  
    31  func (s *MySuite) TestSkipSpecIfAllScenariosAreSkipped(c *C) {
    32  	specText := `Specification Heading
    33  =====================
    34  Scenario 1
    35  ----------
    36  * say hello1
    37  
    38  Scenario 2
    39  ----------
    40  * say hello2
    41  `
    42  	p := new(parser.SpecParser)
    43  	spec, _, _ := p.Parse(specText, gauge.NewConceptDictionary(), "")
    44  	err := gauge_messages.StepValidateResponse_STEP_IMPLEMENTATION_NOT_FOUND // nolint
    45  	errs := validationErrors{spec: []error{
    46  		NewStepValidationError(spec.Scenarios[0].Steps[0], "", "", &err, ""),
    47  		NewStepValidationError(spec.Scenarios[1].Steps[0], "", "", &err, ""),
    48  	}}
    49  
    50  	errMap := getErrMap(gauge.NewBuildErrors(), errs)
    51  
    52  	c.Assert(len(errMap.SpecErrs), Equals, 1)
    53  	c.Assert(len(errMap.ScenarioErrs), Equals, 2)
    54  	c.Assert(len(errMap.StepErrs), Equals, 2)
    55  }
    56  
    57  func (s *MySuite) TestDoesNotSkipSpecIfAllScenariosAreNotSkipped(c *C) {
    58  	specText := `Specification Heading
    59  =====================
    60  Scenario 1
    61  ----------
    62  * say hello1
    63  
    64  Scenario 2
    65  ----------
    66  * say hello2
    67  `
    68  	p := new(parser.SpecParser)
    69  	spec, _, _ := p.Parse(specText, gauge.NewConceptDictionary(), "")
    70  	err := gauge_messages.StepValidateResponse_STEP_IMPLEMENTATION_NOT_FOUND // nolint
    71  
    72  	errs := validationErrors{spec: []error{
    73  		NewStepValidationError(spec.Scenarios[0].Steps[0], "", "", &err, ""),
    74  	}}
    75  
    76  	errMap := getErrMap(gauge.NewBuildErrors(), errs)
    77  
    78  	c.Assert(len(errMap.SpecErrs), Equals, 0)
    79  	c.Assert(len(errMap.ScenarioErrs), Equals, 1)
    80  	c.Assert(len(errMap.StepErrs), Equals, 1)
    81  }
    82  
    83  func (s *MySuite) TestSkipSpecIfNoScenariosPresent(c *C) {
    84  	specText := `Specification Heading
    85  =====================
    86  * say hello1
    87  * say hello2
    88  `
    89  	p := new(parser.SpecParser)
    90  	spec, _, _ := p.Parse(specText, gauge.NewConceptDictionary(), "")
    91  
    92  	errs := validationErrors{spec: []error{}}
    93  
    94  	errMap := getErrMap(gauge.NewBuildErrors(), errs)
    95  
    96  	c.Assert(len(errMap.SpecErrs), Equals, 0)
    97  	c.Assert(len(errMap.ScenarioErrs), Equals, 0)
    98  	c.Assert(len(errMap.StepErrs), Equals, 0)
    99  }
   100  
   101  func (s *MySuite) TestSkipSpecIfTableRowOutOfRange(c *C) {
   102  	specText := `Specification Heading
   103  =====================
   104  Scenario 1
   105  ----------
   106  * say hello1
   107  
   108  Scenario 2
   109  ----------
   110  * say hello2
   111  `
   112  	p := new(parser.SpecParser)
   113  	spec, _, _ := p.Parse(specText, gauge.NewConceptDictionary(), "")
   114  
   115  	errs := validationErrors{spec: []error{
   116  		NewSpecValidationError("Table row out of range", spec.FileName),
   117  	}}
   118  
   119  	errMap := getErrMap(gauge.NewBuildErrors(), errs)
   120  
   121  	c.Assert(len(errMap.SpecErrs), Equals, 1)
   122  	c.Assert(len(errMap.ScenarioErrs), Equals, 0)
   123  	c.Assert(len(errMap.StepErrs), Equals, 0)
   124  }
   125  
   126  func (s *MySuite) TestValidateStep(c *C) {
   127  	HideSuggestion = false
   128  	var suggestion bytes.Buffer
   129  	myStep := &gauge.Step{Value: "my step", LineText: "my step", IsConcept: false, LineNo: 3}
   130  	runner := &mockRunner{
   131  		ExecuteMessageFunc: func(m *gauge_messages.Message) (*gauge_messages.Message, error) {
   132  			suggestion.WriteString("\n\t@Step(\"my step\")\n\tpublic void implementation1(){\n\t\t// your code here...\n\t}")
   133  			res := &gauge_messages.StepValidateResponse{IsValid: false, ErrorMessage: "my err msg", ErrorType: gauge_messages.StepValidateResponse_STEP_IMPLEMENTATION_NOT_FOUND, Suggestion: suggestion.String()}
   134  			return &gauge_messages.Message{MessageType: gauge_messages.Message_StepValidateResponse, StepValidateResponse: res}, nil
   135  		},
   136  	}
   137  	specVal := &SpecValidator{specification: &gauge.Specification{FileName: "foo.spec"}, runner: runner}
   138  	valErr := specVal.validateStep(myStep)
   139  
   140  	c.Assert(valErr, Not(Equals), nil)
   141  	c.Assert(valErr.Error(), Equals, "foo.spec:3 Step implementation not found => 'my step'")
   142  	c.Assert(valErr.(StepValidationError).Suggestion(), Equals, "\n\t"+
   143  		"@Step(\"my step\")\n\t"+
   144  		"public void implementation1(){\n\t"+
   145  		"\t// your code here...\n\t"+
   146  		"}")
   147  }
   148  
   149  func (s *MySuite) TestShouldNotGiveSuggestionWhenHideSuggestionFlagIsFalse(c *C) {
   150  	HideSuggestion = true
   151  	myStep := &gauge.Step{Value: "my step", LineText: "my step", IsConcept: false, LineNo: 3}
   152  	runner := &mockRunner{
   153  		ExecuteMessageFunc: func(m *gauge_messages.Message) (*gauge_messages.Message, error) {
   154  			res := &gauge_messages.StepValidateResponse{IsValid: false, ErrorMessage: "my err msg", ErrorType: gauge_messages.StepValidateResponse_STEP_IMPLEMENTATION_NOT_FOUND}
   155  			return &gauge_messages.Message{MessageType: gauge_messages.Message_StepValidateResponse, StepValidateResponse: res}, nil
   156  		},
   157  	}
   158  	specVal := &SpecValidator{specification: &gauge.Specification{FileName: "foo.spec"}, runner: runner}
   159  	valErr := specVal.validateStep(myStep)
   160  
   161  	c.Assert(valErr, Not(Equals), nil)
   162  	c.Assert(valErr.Error(), Equals, "foo.spec:3 Step implementation not found => 'my step'")
   163  	c.Assert(valErr.(StepValidationError).suggestion, Equals, "")
   164  }
   165  
   166  func (s *MySuite) TestValidateStepInConcept(c *C) {
   167  	HideSuggestion = false
   168  	var suggestion bytes.Buffer
   169  	parentStep := &gauge.Step{Value: "my concept", LineNo: 2, IsConcept: true, LineText: "my concept"}
   170  	myStep := &gauge.Step{Value: "my step", LineText: "my step", IsConcept: false, LineNo: 3, Parent: parentStep}
   171  	cptDict := gauge.NewConceptDictionary()
   172  	cptDict.ConceptsMap["my concept"] = &gauge.Concept{ConceptStep: parentStep, FileName: "concept.cpt"}
   173  	runner := &mockRunner{
   174  		ExecuteMessageFunc: func(m *gauge_messages.Message) (*gauge_messages.Message, error) {
   175  			suggestion.WriteString("\n\t@Step(\"my step\")\n\tpublic void implementation1(){\n\t\t// your code here...\n\t}")
   176  			res := &gauge_messages.StepValidateResponse{IsValid: false, ErrorMessage: "my err msg", ErrorType: gauge_messages.StepValidateResponse_STEP_IMPLEMENTATION_NOT_FOUND, Suggestion: suggestion.String()}
   177  			return &gauge_messages.Message{MessageType: gauge_messages.Message_StepValidateResponse, StepValidateResponse: res}, nil
   178  		},
   179  	}
   180  
   181  	specVal := &SpecValidator{specification: &gauge.Specification{FileName: "foo.spec"}, conceptsDictionary: cptDict, runner: runner}
   182  	valErr := specVal.validateStep(myStep)
   183  
   184  	c.Assert(valErr, Not(Equals), nil)
   185  	c.Assert(valErr.Error(), Equals, "concept.cpt:3 Step implementation not found => 'my step'")
   186  	c.Assert(valErr.(StepValidationError).Suggestion(), Equals, "\n\t@Step(\"my step\")\n\t"+
   187  		"public void implementation1(){\n\t"+
   188  		"\t// your code here...\n\t"+
   189  		"}")
   190  }
   191  
   192  func (s *MySuite) TestFilterDuplicateValidationErrors(c *C) {
   193  	specText := `Specification Heading
   194  =====================
   195  Scenario 1
   196  ----------
   197  * abc
   198  
   199  Scenario 2
   200  ----------
   201  * hello
   202  `
   203  	step := gauge.Step{
   204  		Value: "abc",
   205  	}
   206  	step1 := gauge.Step{
   207  		Value: "helo",
   208  	}
   209  	implNotFoundError := StepValidationError{
   210  		step:       &step,
   211  		errorType:  &implNotFound,
   212  		suggestion: "suggestion",
   213  	}
   214  	dupImplFoundError := StepValidationError{
   215  		step:       &step1,
   216  		errorType:  &dupImplFound,
   217  		suggestion: "suggestion1",
   218  	}
   219  
   220  	p := new(parser.SpecParser)
   221  	spec, _, _ := p.Parse(specText, gauge.NewConceptDictionary(), "")
   222  
   223  	errs := validationErrors{spec: []error{
   224  		implNotFoundError,
   225  		implNotFoundError,
   226  		dupImplFoundError,
   227  	}}
   228  
   229  	want := []error{implNotFoundError, dupImplFoundError}
   230  
   231  	got := FilterDuplicates(errs)
   232  
   233  	c.Assert(got, DeepEquals, want)
   234  }
   235  
   236  type tableRow struct {
   237  	name           string
   238  	input          string
   239  	tableRowsCount int
   240  	err            error
   241  }
   242  
   243  var tableRowTests = []*tableRow{
   244  	{"Valid single row number", "3", 5, nil},
   245  	{"Invalid single row number", "2", 1, errors.New("Table rows range validation failed => Table row number '2' is out of range")},
   246  	{"Valid row numbers list", "2,3,4", 4, nil},
   247  	{"Invalid list with empty value", ",3,4", 4, errors.New("Table rows range validation failed => Row number cannot be empty")},
   248  	{"Invalid row numbers list", "2,3,4", 3, errors.New("Table rows range validation failed => Table row number '4' is out of range")},
   249  	{"Invalid row numbers list with special chars", "2*&", 3, errors.New("Table rows range validation failed => Failed to parse '2*&' to row number")},
   250  	{"Valid table rows range", "2-5", 5, nil},
   251  	{"Invalid table rows range", "2-5", 4, errors.New("Table rows range validation failed => Table row number '5' is out of range")},
   252  	{"Invalid table rows range", "2-2", 4, nil},
   253  	{"Invalid table rows with character", "a", 4, errors.New("Table rows range validation failed => Failed to parse 'a' to row number")},
   254  	{"Invalid table rows range with character", "a-5", 5, errors.New("Table rows range validation failed => Failed to parse 'a' to row number")},
   255  	{"Invalid table rows range with string", "a-qwerty", 4, errors.New("Table rows range validation failed => Failed to parse 'a' to row number")},
   256  	{"Empty table rows range", "", 4, nil},
   257  	{"Table rows range with multiple -", "2-3-4", 4, errors.New("Table rows range '2-3-4' is invalid => Table rows range should be of format rowNumber-rowNumber")},
   258  	{"Table rows range with different separator", "2:4", 4, errors.New("Table rows range validation failed => Failed to parse '2:4' to row number")},
   259  	{"Table rows list with spaces", "2, 4 ", 4, nil},
   260  	{"Row count is zero with empty input", "", 0, nil},
   261  	{"Row count is zero with non empty input", "1", 0, errors.New("Table rows range validation failed => Table row number '1' is out of range")},
   262  	{"Row count is non-zero with empty input", "", 2, nil},
   263  	{"Row count is non-zero with non-empty input", "2", 2, nil},
   264  }
   265  
   266  func (s *MySuite) TestToValidateDataTableRowsRangeFromInputFlag(c *C) {
   267  	for _, test := range tableRowTests {
   268  		TableRows = test.input
   269  		got := validateDataTableRange(test.tableRowsCount)
   270  		want := test.err
   271  		c.Assert(got, DeepEquals, want, Commentf(test.name))
   272  	}
   273  }
   274  
   275  type mockRunner struct {
   276  	ExecuteMessageFunc func(m *gauge_messages.Message) (*gauge_messages.Message, error)
   277  }
   278  
   279  func (r *mockRunner) ExecuteMessageWithTimeout(m *gauge_messages.Message) (*gauge_messages.Message, error) {
   280  	return r.ExecuteMessageFunc(m)
   281  }
   282  func (r *mockRunner) ExecuteAndGetStatus(m *gauge_messages.Message) *gauge_messages.ProtoExecutionResult {
   283  	return nil
   284  }
   285  
   286  func (r *mockRunner) Alive() bool {
   287  	return false
   288  }
   289  
   290  func (r *mockRunner) Kill() error {
   291  	return nil
   292  }
   293  
   294  func (r *mockRunner) Connection() net.Conn {
   295  	return nil
   296  }
   297  
   298  func (r *mockRunner) IsMultithreaded() bool {
   299  	return false
   300  }
   301  
   302  func (r *mockRunner) Info() *runner.RunnerInfo {
   303  	return nil
   304  }
   305  
   306  func (r *mockRunner) Pid() int {
   307  	return -1
   308  }