149 строки
5,2 КиБ
Markdown
149 строки
5,2 КиБ
Markdown
[](https://travis-ci.org/DATA-DOG/godog)
|
||
[](https://godoc.org/github.com/DATA-DOG/godog)
|
||
|
||
# Godog
|
||
|
||
**Godog** is an open source behavior-driven development framework for [go][golang] programming language.
|
||
What is behavior-driven development, you ask? It’s the idea that you start by writing human-readable sentences that
|
||
describe a feature of your application and how it should work, and only then implement this behavior in software.
|
||
|
||
The project is inspired by [behat][behat] and [cucumber][cucumber] and is based on cucumber [gherkin3 parser][gherkin].
|
||
|
||
**Godog** does not intervene with the standard **go test** command and it's behavior. You can leverage both frameworks
|
||
to functionally test your application while maintaining all test related source code in **_test.go** files.
|
||
|
||
**Godog** acts similar compared to **go test** command. It builds all package sources to a single main package file
|
||
and replaces **main** func with it's own and runs the build to test described application behavior in feature files.
|
||
Production builds remain clean without any test related source code.
|
||
|
||
The public [API][godoc] is small and should be stable for the future releases. Something may be added or exported, but
|
||
not changed most likely. I'll try to respect **backward compatibility** as much as possible.
|
||
|
||
### Install
|
||
|
||
go get github.com/DATA-DOG/godog/cmd/godog
|
||
|
||
### Example
|
||
|
||
Imagine we have a **godog cart** to serve godogs for dinner. At first, we describe our feature
|
||
in plain text:
|
||
|
||
``` gherkin
|
||
# file: /tmp/godog/godog.feature
|
||
Feature: eat godogs
|
||
In order to be happy
|
||
As a hungry gopher
|
||
I need to be able to eat godogs
|
||
|
||
Scenario: Eat 5 out of 12
|
||
Given there are 12 godogs
|
||
When I eat 5
|
||
Then there should be 7 remaining
|
||
```
|
||
|
||
As a developer, your work is done as soon as you’ve made the program behave as
|
||
described in the Scenario.
|
||
|
||
If you run `godog godog.feature` inside the **/tmp/godog** directory.
|
||
You should see that the steps are undefined:
|
||
|
||

|
||
|
||
It gives you undefined step snippets to implement in your test context. You may copy these snippets
|
||
into **godog_test.go** file.
|
||
|
||
Now if you run the tests again. You should see that the definition is now pending. You may change
|
||
**ErrPending** to **nil** and the scenario will pass successfully.
|
||
|
||
Since we need a working implementation, we may start by implementing what is necessary.
|
||
We only need a number of **godogs** for now.
|
||
|
||
``` go
|
||
/* file: /tmp/godog/godog.go */
|
||
package main
|
||
|
||
var Godogs int
|
||
|
||
func main() { /* usual main func */ }
|
||
```
|
||
|
||
Now lets finish our step implementations in order to test our feature requirements:
|
||
|
||
``` go
|
||
/* file: /tmp/godog/godog_test.go */
|
||
package main
|
||
|
||
import (
|
||
"fmt"
|
||
|
||
"github.com/DATA-DOG/godog"
|
||
)
|
||
|
||
func thereAreGodogs(available int) error {
|
||
Godogs = available
|
||
return nil
|
||
}
|
||
|
||
func iEat(num int) error {
|
||
if Godogs < num {
|
||
return fmt.Errorf("you cannot eat %d godogs, there are %d available", num, Godogs)
|
||
}
|
||
Godogs -= num
|
||
return nil
|
||
}
|
||
|
||
func thereShouldBeRemaining(remaining int) error {
|
||
if Godogs != remaining {
|
||
return fmt.Errorf("expected %d godogs to be remaining, but there is %d", remaining, Godogs)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func featureContext(s godog.Suite) {
|
||
s.Step(`^there are (\d+) godogs$`, thereAreGodogs)
|
||
s.Step(`^I eat (\d+)$`, iEat)
|
||
s.Step(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
|
||
|
||
s.BeforeScenario(func(interface{}) {
|
||
Godogs = 0 // clean the state before every scenario
|
||
})
|
||
}
|
||
```
|
||
|
||
Now when you run the `godog godog.feature` again, you should see:
|
||
|
||

|
||
|
||
**Note:** we have hooked to **BeforeScenario** event in order to reset state. You may hook into
|
||
more events, like **AfterStep** to test against an error and print more details about the error
|
||
or state before failure. Or **BeforeSuite** to prepare a database.
|
||
|
||
### Documentation
|
||
|
||
See [godoc][godoc] for general API details.
|
||
See **.travis.yml** for supported **go** versions.
|
||
See `godog -h` for general command options.
|
||
|
||
### FAQ
|
||
|
||
**Q:** Where can I configure common options globally?
|
||
**A:** You can't. Alias your common or project based commands: `alias godog-wip="godog --format=progress --tags=@wip"`
|
||
|
||
### Contributions
|
||
|
||
Feel free to open a pull request. Note, if you wish to contribute an extension to public (exported methods or types) -
|
||
please open an issue before to discuss whether these changes can be accepted. All backward incompatible changes are
|
||
and will be treated cautiously.
|
||
|
||
### License
|
||
|
||
All package dependencies are **MIT** or **BSD** licensed.
|
||
|
||
**Godog** is licensed under the [three clause BSD license][license]
|
||
|
||
[godoc]: http://godoc.org/github.com/DATA-DOG/godog "Documentation on godoc"
|
||
[golang]: https://golang.org/ "GO programming language"
|
||
[behat]: http://docs.behat.org/ "Behavior driven development framework for PHP"
|
||
[cucumber]: https://cucumber.io/ "Behavior driven development framework for Ruby"
|
||
[gherkin]: https://github.com/cucumber/gherkin-go "Gherkin3 parser for GO"
|
||
[license]: http://en.wikipedia.org/wiki/BSD_licenses "The three clause BSD license"
|