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