github.com/lonnblad/godog@v0.7.14-0.20200306004719-1b0cb3259847/README.md (about)

     1  [![CircleCI](https://circleci.com/gh/cucumber/godog/tree/master.svg?style=svg)](https://circleci.com/gh/cucumber/godog/tree/master)
     2  [![GoDoc](https://godoc.org/github.com/cucumber/godog?status.svg)](https://godoc.org/github.com/cucumber/godog)
     3  [![codecov](https://codecov.io/gh/cucumber/godog/branch/master/graph/badge.svg)](https://codecov.io/gh/cucumber/godog)
     4  
     5  # Godog
     6  
     7  <p align="center"><img src="/logo.png" alt="Godog logo" style="width:250px;" /></p>
     8  
     9  **The API is likely to change a few times before we reach 1.0.0**
    10  
    11  Please read all the README, you may find it very useful. And do not forget
    12  to peek into the
    13  [CHANGELOG](https://github.com/cucumber/godog/blob/master/CHANGELOG.md)
    14  from time to time.
    15  
    16  Package godog is the official Cucumber BDD framework for Golang, it merges
    17  specification and test documentation into one cohesive whole. The author
    18  is a member of [cucumber team](https://github.com/cucumber).
    19  
    20  The project is inspired by [behat][behat] and [cucumber][cucumber] and is
    21  based on cucumber [gherkin3 parser][gherkin].
    22  
    23  **Godog** does not intervene with the standard **go test** command
    24  behavior. You can leverage both frameworks to functionally test your
    25  application while maintaining all test related source code in **_test.go**
    26  files.
    27  
    28  **Godog** acts similar compared to **go test** command, by using go
    29  compiler and linker tool in order to produce test executable. Godog
    30  contexts need to be exported the same way as **Test** functions for go
    31  tests. Note, that if you use **godog** command tool, it will use `go`
    32  executable to determine compiler and linker.
    33  
    34  **Godog** ships gherkin parser dependency as a subpackage. This will
    35  ensure that it is always compatible with the installed version of godog.
    36  So in general there are no vendor dependencies needed for installation.
    37  
    38  The following about section was taken from
    39  [cucumber](https://cucumber.io/) homepage.
    40  
    41  ## About
    42  
    43  #### A single source of truth
    44  
    45  Cucumber merges specification and test documentation into one cohesive whole.
    46  
    47  #### Living documentation
    48  
    49  Because they're automatically tested by Cucumber, your specifications are
    50  always bang up-to-date.
    51  
    52  #### Focus on the customer
    53  
    54  Business and IT don't always understand each other. Cucumber's executable
    55  specifications encourage closer collaboration, helping teams keep the
    56  business goal in mind at all times.
    57  
    58  #### Less rework
    59  
    60  When automated testing is this much fun, teams can easily protect
    61  themselves from costly regressions.
    62  
    63  ## Install
    64  
    65      go get github.com/cucumber/godog/cmd/godog
    66  
    67  ## Example
    68  
    69  The following example can be [found
    70  here](/_examples/godogs).
    71  
    72  ### Step 1
    73  
    74  Given we create a new go package **$GOPATH/src/godogs**. From now on, this
    75  is our work directory `cd $GOPATH/src/godogs`.
    76  
    77  Imagine we have a **godog cart** to serve godogs for lunch. First of all,
    78  we describe our feature in plain text - `vim
    79  $GOPATH/src/godogs/features/godogs.feature`:
    80  
    81  ``` gherkin
    82  # file: $GOPATH/src/godogs/features/godogs.feature
    83  Feature: eat godogs
    84    In order to be happy
    85    As a hungry gopher
    86    I need to be able to eat godogs
    87  
    88    Scenario: Eat 5 out of 12
    89      Given there are 12 godogs
    90      When I eat 5
    91      Then there should be 7 remaining
    92  ```
    93  
    94  **NOTE:** same as **go test** godog respects package level isolation. All
    95  your step definitions should be in your tested package root directory. In
    96  this case - `$GOPATH/src/godogs`
    97  
    98  ### Step 2
    99  
   100  If godog is installed in your GOPATH. We can run `godog` inside the
   101  **$GOPATH/src/godogs** directory. You should see that the steps are
   102  undefined:
   103  
   104  ![Undefined step snippets](/screenshots/undefined.png?raw=true)
   105  
   106  If we wish to vendor godog dependency, we can do it as usual, using tools
   107  you prefer:
   108  
   109      git clone https://github.com/cucumber/godog.git $GOPATH/src/godogs/vendor/github.com/cucumber/godog
   110  
   111  It gives you undefined step snippets to implement in your test context.
   112  You may copy these snippets into your `godogs_test.go` file.
   113  
   114  Our directory structure should now look like:
   115  
   116  ![Directory layout](/screenshots/dir-tree.png?raw=true)
   117  
   118  If you copy the snippets into our test file and run godog again. We should
   119  see the step definition is now pending:
   120  
   121  ![Pending step definition](/screenshots/pending.png?raw=true)
   122  
   123  You may change **ErrPending** to **nil** and the scenario will
   124  pass successfully.
   125  
   126  Since we need a working implementation, we may start by implementing only what is necessary.
   127  
   128  ### Step 3
   129  
   130  We only need a number of **godogs** for now. Lets keep it simple.
   131  
   132  ``` go
   133  /* file: $GOPATH/src/godogs/godogs.go */
   134  package main
   135  
   136  // Godogs available to eat
   137  var Godogs int
   138  
   139  func main() { /* usual main func */ }
   140  ```
   141  
   142  ### Step 4
   143  
   144  Now lets implement our step definitions, which we can copy from generated
   145  console output snippets in order to test our feature requirements:
   146  
   147  ``` go
   148  /* file: $GOPATH/src/godogs/godogs_test.go */
   149  package main
   150  
   151  import (
   152  	"fmt"
   153  
   154  	"github.com/cucumber/godog"
   155  	messages "github.com/cucumber/messages-go/v9"
   156  )
   157  
   158  func thereAreGodogs(available int) error {
   159  	Godogs = available
   160  	return nil
   161  }
   162  
   163  func iEat(num int) error {
   164  	if Godogs < num {
   165  		return fmt.Errorf("you cannot eat %d godogs, there are %d available", num, Godogs)
   166  	}
   167  	Godogs -= num
   168  	return nil
   169  }
   170  
   171  func thereShouldBeRemaining(remaining int) error {
   172  	if Godogs != remaining {
   173  		return fmt.Errorf("expected %d godogs to be remaining, but there is %d", remaining, Godogs)
   174  	}
   175  	return nil
   176  }
   177  
   178  func FeatureContext(s *godog.Suite) {
   179  	s.Step(`^there are (\d+) godogs$`, thereAreGodogs)
   180  	s.Step(`^I eat (\d+)$`, iEat)
   181  	s.Step(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
   182  
   183  	s.BeforeScenario(func(*messages.Pickle) {
   184  		Godogs = 0 // clean the state before every scenario
   185  	})
   186  }
   187  ```
   188  
   189  Now when you run the `godog` again, you should see:
   190  
   191  ![Passed suite](/screenshots/passed.png?raw=true)
   192  
   193  We have hooked to **BeforeScenario** event in order to reset application
   194  state before each scenario. You may hook into more events, like
   195  **AfterStep** to print all state in case of an error. Or
   196  **BeforeSuite** to prepare a database.
   197  
   198  By now, you should have figured out, how to use **godog**. Another advice
   199  is to make steps orthogonal, small and simple to read for a user. Whether
   200  the user is a dumb website user or an API developer, who may understand
   201  a little more technical context - it should target that user.
   202  
   203  When steps are orthogonal and small, you can combine them just like you do
   204  with Unix tools. Look how to simplify or remove ones, which can be
   205  composed.
   206  
   207  ### References and Tutorials
   208  
   209  - [cucumber-html-reporter](https://github.com/gkushang/cucumber-html-reporter)
   210    may be used in order to generate **html** reports together with
   211    **cucumber** output formatter. See the [following docker
   212    image](https://github.com/myie/cucumber-html-reporter) for usage
   213    details.
   214  - [how to use godog by semaphoreci](https://semaphoreci.com/community/tutorials/how-to-use-godog-for-behavior-driven-development-in-go)
   215  - see [examples](https://github.com/cucumber/godog/tree/master/_examples)
   216  - see extension [AssistDog](https://github.com/hellomd/assistdog), which
   217    may have useful **gherkin.DataTable** transformations or comparison
   218    methods for assertions.
   219  
   220  ### Documentation
   221  
   222  See [godoc][godoc] for general API details.
   223  See **[Circle Config](/.circleci/config.yml)** for supported **go** versions.
   224  See `godog -h` for general command options.
   225  
   226  See implementation examples:
   227  
   228  - [rest API server](/_examples/api)
   229  - [rest API with Database](/_examples/db)
   230  - [godogs](/_examples/godogs)
   231  
   232  ## FAQ
   233  
   234  ### Running Godog with go test
   235  
   236  You may integrate running **godog** in your **go test** command. You can
   237  run it using go [TestMain](https://golang.org/pkg/testing/#hdr-Main) func
   238  available since **go 1.4**. In this case it is not necessary to have
   239  **godog** command installed. See the following examples.
   240  
   241  The following example binds **godog** flags with specified prefix `godog`
   242  in order to prevent flag collisions.
   243  
   244  ``` go
   245  var opt = godog.Options{
   246  	Output: colors.Colored(os.Stdout),
   247  	Format: "progress", // can define default values
   248  }
   249  
   250  func init() {
   251  	godog.BindFlags("godog.", flag.CommandLine, &opt)
   252  }
   253  
   254  func TestMain(m *testing.M) {
   255  	flag.Parse()
   256  	opt.Paths = flag.Args()
   257  
   258  	status := godog.RunWithOptions("godogs", func(s *godog.Suite) {
   259  		FeatureContext(s)
   260  	}, opt)
   261  
   262  	if st := m.Run(); st > status {
   263  		status = st
   264  	}
   265  	os.Exit(status)
   266  }
   267  ```
   268  
   269  Then you may run tests with by specifying flags in order to filter
   270  features.
   271  
   272  ```
   273  go test -v --godog.random --godog.tags=wip
   274  go test -v --godog.format=pretty --godog.random -race -coverprofile=coverage.txt -covermode=atomic
   275  ```
   276  
   277  The following example does not bind godog flags, instead manually
   278  configuring needed options.
   279  
   280  ``` go
   281  func TestMain(m *testing.M) {
   282  	status := godog.RunWithOptions("godog", func(s *godog.Suite) {
   283  		FeatureContext(s)
   284  	}, godog.Options{
   285  		Format:    "progress",
   286  		Paths:     []string{"features"},
   287  		Randomize: time.Now().UTC().UnixNano(), // randomize scenario execution order
   288  	})
   289  
   290  	if st := m.Run(); st > status {
   291  		status = st
   292  	}
   293  	os.Exit(status)
   294  }
   295  ```
   296  
   297  You can even go one step further and reuse **go test** flags, like
   298  **verbose** mode in order to switch godog **format**. See the following
   299  example:
   300  
   301  ``` go
   302  func TestMain(m *testing.M) {
   303  	format := "progress"
   304  	for _, arg := range os.Args[1:] {
   305  		if arg == "-test.v=true" { // go test transforms -v option
   306  			format = "pretty"
   307  			break
   308  		}
   309  	}
   310  	status := godog.RunWithOptions("godog", func(s *godog.Suite) {
   311  		godog.SuiteContext(s)
   312  	}, godog.Options{
   313  		Format: format,
   314  		Paths:     []string{"features"},
   315  	})
   316  
   317  	if st := m.Run(); st > status {
   318  		status = st
   319  	}
   320  	os.Exit(status)
   321  }
   322  ```
   323  
   324  Now when running `go test -v` it will use **pretty** format.
   325  
   326  ### Configure common options for godog CLI
   327  
   328  There are no global options or configuration files. Alias your common or
   329  project based commands: `alias godog-wip="godog --format=progress
   330  --tags=@wip"`
   331  
   332  ### Testing browser interactions
   333  
   334  **godog** does not come with builtin packages to connect to the browser.
   335  You may want to look at [selenium](http://www.seleniumhq.org/) and
   336  probably [phantomjs](http://phantomjs.org/). See also the following
   337  components:
   338  
   339  1. [browsersteps](https://github.com/llonchj/browsersteps) - provides
   340     basic context steps to start selenium and navigate browser content.
   341  2. You may wish to have [goquery](https://github.com/PuerkitoBio/goquery)
   342     in order to work with HTML responses like with JQuery.
   343  
   344  ### Concurrency
   345  
   346  In order to support concurrency well, you should reset the state and
   347  isolate each scenario. They should not share any state. It is suggested to
   348  run the suite concurrently in order to make sure there is no state
   349  corruption or race conditions in the application.
   350  
   351  It is also useful to randomize the order of scenario execution, which you
   352  can now do with **--random** command option.
   353  
   354  **NOTE:** if suite runs with concurrency option, it concurrently runs
   355  every feature, not scenario per different features. This gives
   356  a flexibility to isolate state per feature. For example using
   357  **BeforeFeature** hook, it is possible to spin up costly service and shut
   358  it down only in **AfterFeature** hook and share the service between all
   359  scenarios in that feature. It is not advisable though, because you are
   360  risking having a state dependency.
   361  
   362  ## Contributions
   363  
   364  Feel free to open a pull request. Note, if you wish to contribute an extension to public (exported methods or types) -
   365  please open an issue before to discuss whether these changes can be accepted. All backward incompatible changes are
   366  and will be treated cautiously.
   367  
   368  Reach out to the community on our [Cucumber Slack Community](https://cucumberbdd.slack.com/).
   369  Join [here](https://cucumberbdd-slack-invite.herokuapp.com/).
   370  
   371  ### Popular Cucumber Slack channels for Godog:
   372  - [#help-godog](https://cucumberbdd.slack.com/archives/CTNL1JCVA) - General Godog Adoption Help
   373  - [#committers-go](https://cucumberbdd.slack.com/archives/CA5NJPDJ4) - Golang focused Cucumber Contributors
   374  - [#committers](https://cucumberbdd.slack.com/archives/C62D0FK0E) - General Cucumber Contributors
   375  
   376  ## License
   377  - **Godog** is licensed under the [MIT][license]
   378  - **Gherkin** is licensed under the [MIT][license] and developed as
   379  a part of the [cucumber project][cucumber]
   380  
   381  [godoc]: http://godoc.org/github.com/cucumber/godog "Documentation on godoc"
   382  [golang]: https://golang.org/  "GO programming language"
   383  [behat]: http://docs.behat.org/ "Behavior driven development framework for PHP"
   384  [cucumber]: https://cucumber.io/ "Behavior driven development framework"
   385  [gherkin]: https://github.com/cucumber/gherkin-go "Gherkin3 parser for GO"
   386  [license]: https://en.wikipedia.org/wiki/MIT_License "The MIT license"