blob: e9d5560bcdf0a5efa0b79f3a4a60d1a09cdcf579 [file] [log] [blame] [view]
jrperritt94ae0eb2016-07-11 22:53:34 -05001# Contributing to Gophercloud
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +02002
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +02003- [Getting started](#getting-started)
4- [Tests](#tests)
5- [Style guide](#basic-style-guide)
jrperritt94ae0eb2016-07-11 22:53:34 -05006- [3 ways to get involved](#5-ways-to-get-involved)
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +02007
Jamie Hannafordd2773f22014-10-07 16:06:23 +02008## Setting up your git workspace
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +02009
Jamie Hannafordd2773f22014-10-07 16:06:23 +020010As a contributor you will need to setup your workspace in a slightly different
11way than just downloading it. Here are the basic installation instructions:
12
Jamie Hannafordbc35d052014-10-07 16:27:30 +0200131. Configure your `$GOPATH` and run `go get` as described in the main
Rickard von Essenf66314b2016-02-13 11:35:00 +010014[README](/README.md#how-to-install) but add `-tags "fixtures acceptance"` to
15get dependencies for unit and acceptance tests.
Jamie Hannafordd2773f22014-10-07 16:06:23 +020016
Carolyn Van Slyck30846442016-07-18 15:03:14 -050017 ```bash
18 go get -tags "fixtures acceptance" github.com/gophercloud/gophercloud
19 ```
20
Jamie Hannafordd2773f22014-10-07 16:06:23 +0200212. Move into the directory that houses your local repository:
22
Jamie Hannaford54bbe992014-10-07 16:50:32 +020023 ```bash
jrperritt55fb5842016-04-13 14:16:08 -050024 cd ${GOPATH}/src/github.com/gophercloud/gophercloud
Jamie Hannaford54bbe992014-10-07 16:50:32 +020025 ```
Jamie Hannafordd2773f22014-10-07 16:06:23 +020026
jrperritt55fb5842016-04-13 14:16:08 -0500273. Fork the `gophercloud/gophercloud` repository and update your remote refs. You
Jamie Hannafordd2773f22014-10-07 16:06:23 +020028will need to rename the `origin` remote branch to `upstream`, and add your
29fork as `origin` instead:
30
Jamie Hannaford54bbe992014-10-07 16:50:32 +020031 ```bash
32 git remote rename origin upstream
Carolyn Van Slyck30846442016-07-18 15:03:14 -050033 git remote add origin git@github.com:<my_username>/gophercloud.git
Jamie Hannaford54bbe992014-10-07 16:50:32 +020034 ```
Jamie Hannafordd2773f22014-10-07 16:06:23 +020035
jrperritt1d8b6f12015-08-14 12:17:09 -0600364. Checkout the latest development branch:
Jamie Hannafordd2773f22014-10-07 16:06:23 +020037
Jamie Hannaford54bbe992014-10-07 16:50:32 +020038 ```bash
jrperritt1d8b6f12015-08-14 12:17:09 -060039 git checkout master
Jamie Hannaford54bbe992014-10-07 16:50:32 +020040 ```
Jamie Hannafordd2773f22014-10-07 16:06:23 +020041
425. If you're working on something (discussed more in detail below), you will
43need to checkout a new feature branch:
44
Jamie Hannaford54bbe992014-10-07 16:50:32 +020045 ```bash
46 git checkout -b my-new-feature
47 ```
Jamie Hannafordd2773f22014-10-07 16:06:23 +020048
49Another thing to bear in mind is that you will need to add a few extra
50environment variables for acceptance tests - this is documented in our
51[acceptance tests readme](/acceptance).
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +020052
53## Tests
54
55When working on a new or existing feature, testing will be the backbone of your
56work since it helps uncover and prevent regressions in the codebase. There are
jrperritt55fb5842016-04-13 14:16:08 -050057two types of test we use in Gophercloud: unit tests and acceptance tests, which
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +020058are both described below.
59
60### Unit tests
61
jrperritt55fb5842016-04-13 14:16:08 -050062Unit tests are the fine-grained tests that establish and ensure the behavior
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +020063of individual units of functionality. We usually test on an
64operation-by-operation basis (an operation typically being an API action) with
65the use of mocking to set up explicit expectations. Each operation will set up
66its HTTP response expectation, and then test how the system responds when fed
67this controlled, pre-determined input.
68
69To make life easier, we've introduced a bunch of test helpers to simplify the
70process of testing expectations with assertions:
71
72```go
73import (
74 "testing"
75
jrperritt55fb5842016-04-13 14:16:08 -050076 "github.com/gophercloud/gophercloud/testhelper"
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +020077)
78
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +020079func TestSomething(t *testing.T) {
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +020080 result, err := Operation()
81
82 testhelper.AssertEquals(t, "foo", result.Bar)
83 testhelper.AssertNoErr(t, err)
84}
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +020085
86func TestSomethingElse(t *testing.T) {
87 testhelper.CheckEquals(t, "expected", "actual")
88}
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +020089```
90
91`AssertEquals` and `AssertNoErr` will throw a fatal error if a value does not
92match an expected value or if an error has been declared, respectively. You can
93also use `CheckEquals` and `CheckNoErr` for the same purpose; the only difference
94being that `t.Errorf` is raised rather than `t.Fatalf`.
95
96Here is a truncated example of mocked HTTP responses:
97
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +020098```go
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +020099import (
100 "testing"
101
jrperritt55fb5842016-04-13 14:16:08 -0500102 th "github.com/gophercloud/gophercloud/testhelper"
103 fake "github.com/gophercloud/gophercloud/testhelper/client"
jrperritt94ae0eb2016-07-11 22:53:34 -0500104 "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200105)
106
107func TestGet(t *testing.T) {
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +0200108 // Setup the HTTP request multiplexer and server
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200109 th.SetupHTTP()
110 defer th.TeardownHTTP()
111
112 th.Mux.HandleFunc("/networks/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
113 // Test we're using the correct HTTP method
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +0200114 th.TestMethod(t, r, "GET")
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200115
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +0200116 // Test we're setting the auth token
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200117 th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
118
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +0200119 // Set the appropriate headers for our mocked response
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200120 w.Header().Add("Content-Type", "application/json")
121 w.WriteHeader(http.StatusOK)
122
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +0200123 // Set the HTTP body
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200124 fmt.Fprintf(w, `
125{
126 "network": {
127 "status": "ACTIVE",
128 "name": "private-network",
129 "admin_state_up": true,
130 "tenant_id": "4fd44f30292945e481c7b8a0c8908869",
131 "shared": true,
132 "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
133 }
134}
135 `)
136 })
137
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +0200138 // Call our API operation
jrperritt94ae0eb2016-07-11 22:53:34 -0500139 network, err := networks.Get(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract()
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200140
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +0200141 // Assert no errors and equality
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200142 th.AssertNoErr(t, err)
143 th.AssertEquals(t, n.Status, "ACTIVE")
144}
145```
146
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +0200147### Acceptance tests
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200148
149As we've already mentioned, unit tests have a very narrow and confined focus -
jrperritt55fb5842016-04-13 14:16:08 -0500150they test small units of behavior. Acceptance tests on the other hand have a
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200151far larger scope: they are fully functional tests that test the entire API of a
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +0200152service in one fell swoop. They don't care about unit isolation or mocking
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200153expectations, they instead do a full run-through and consequently test how the
154entire system _integrates_ together. When an API satisfies expectations, it
155proves by default that the requirements for a contract have been met.
156
Jamie Hannafordd2773f22014-10-07 16:06:23 +0200157Please be aware that acceptance tests will hit a live API - and may incur
158service charges from your provider. Although most tests handle their own
159teardown procedures, it is always worth manually checking that resources are
160deleted after the test suite finishes.
161
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200162### Running tests
163
164To run all tests:
165
166```bash
Rickard von Essenf66314b2016-02-13 11:35:00 +0100167go test -tags fixtures ./...
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200168```
169
170To run all tests with verbose output:
171
172```bash
Rickard von Essenf66314b2016-02-13 11:35:00 +0100173go test -v -tags fixtures ./...
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200174```
175
176To run tests that match certain [build tags]():
177
178```bash
Rickard von Essenf66314b2016-02-13 11:35:00 +0100179go test -tags "fixtures foo bar" ./...
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200180```
181
182To run tests for a particular sub-package:
183
184```bash
Rickard von Essenf66314b2016-02-13 11:35:00 +0100185cd ./path/to/package && go test -tags fixtures .
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200186```
187
jrperritt55fb5842016-04-13 14:16:08 -0500188## Style guide
189
jrperritt9b7b9e62016-07-11 22:30:50 -0500190See [here](/STYLEGUIDE.md)
jrperritt55fb5842016-04-13 14:16:08 -0500191
jrperritt9b7b9e62016-07-11 22:30:50 -0500192## 3 ways to get involved
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200193
Jamie Hannafordd2773f22014-10-07 16:06:23 +0200194There are five main ways you can get involved in our open-source project, and
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200195each is described briefly below. Once you've made up your mind and decided on
196your fix, you will need to follow the same basic steps that all submissions are
197required to adhere to:
198
jrperritt55fb5842016-04-13 14:16:08 -05001991. [fork](https://help.github.com/articles/fork-a-repo/) the `gophercloud/gophercloud` repository
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +02002002. checkout a [new branch](https://github.com/Kunena/Kunena-Forum/wiki/Create-a-new-branch-with-git-and-manage-branches)
Jamie Hannafordd2773f22014-10-07 16:06:23 +02002013. submit your branch as a [pull request](https://help.github.com/articles/creating-a-pull-request/)
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200202
jrperritt9b7b9e62016-07-11 22:30:50 -0500203### 1. Fixing bugs
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200204
205If you want to start fixing open bugs, we'd really appreciate that! Bug fixing
206is central to any project. The best way to get started is by heading to our
jrperritt55fb5842016-04-13 14:16:08 -0500207[bug tracker](https://github.com/gophercloud/gophercloud/issues) and finding open
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200208bugs that you think nobody is working on. It might be useful to comment on the
209thread to see the current state of the issue and if anybody has made any
210breakthroughs on it so far.
211
jrperritt9b7b9e62016-07-11 22:30:50 -0500212### 2. Improving documentation
213The best source of documentation is on [godoc.org](http://godoc.org). It is
214automatically generated from the source code.
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200215
Jamie Hannafordbc35d052014-10-07 16:27:30 +0200216If you feel that a certain section could be improved - whether it's to clarify
217ambiguity, correct a technical mistake, or to fix a grammatical error - please
218feel entitled to do so! We welcome doc pull requests with the same childlike
219enthusiasm as any other contribution!
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200220
jrperritt9b7b9e62016-07-11 22:30:50 -0500221###3. Working on a new feature
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200222
223If you've found something we've left out, definitely feel free to start work on
Jamie Hannafordd2773f22014-10-07 16:06:23 +0200224introducing that feature. It's always useful to open an issue or submit a pull
225request early on to indicate your intent to a core contributor - this enables
226quick/early feedback and can help steer you in the right direction by avoiding
227known issues. It might also help you avoid losing time implementing something
228that might not ever work. One tip is to prefix your Pull Request issue title
229with [wip] - then people know it's a work in progress.
Jamie Hannafordd5a1cb72014-10-07 14:31:27 +0200230
231You must ensure that all of your work is well tested - both in terms of unit
232and acceptance tests. Untested code will not be merged because it introduces
Jamie Hannafordd2b6dfc2014-10-07 14:46:55 +0200233too much of a risk to end-users.
234
235Happy hacking!