Skip to content

Commit c9091c1

Browse files
committed
Add DEVELOPMENT.md.erb file.
1 parent c99c563 commit c9091c1

File tree

1 file changed

+246
-0
lines changed

1 file changed

+246
-0
lines changed
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
# Development Setup
2+
3+
Generally speaking, you only need to clone the project and install
4+
the dependencies with [Bundler](http://bundler.io/). You can either
5+
get a full RSpec development environment using
6+
[rspec-dev](https://github.com/rspec/rspec-dev#README) or you can
7+
set this project up individually.
8+
9+
## Using rspec-dev
10+
11+
See the [rspec-dev README](https://github.com/rspec/rspec-dev#README)
12+
for setup instructions.
13+
14+
The rspec-dev project contains many rake tasks for helping manage
15+
an RSpec development environment, making it easy to do things like:
16+
17+
* Change branches across all repos
18+
* Update all repos with the latest code from `master`
19+
* Cut a new release across all repos
20+
* Push out updated build scripts to all repos
21+
22+
These sorts of tasks are essential for the RSpec maintainers but will
23+
probably be unnecessary complexity if you're just contributing to one
24+
repository. If you are getting setup to make your first contribution,
25+
we recommend you take the simpler route of setting up <%= project_name %>
26+
individually.
27+
28+
## Setting up <%= project_name %> individually
29+
30+
Clone the repo:
31+
32+
```
33+
$ git clone [email protected]:rspec/<%= project_name %>.git
34+
```
35+
36+
Install the dependencies using [Bundler](http://bundler.io/):
37+
38+
```
39+
$ cd <%= project_name %>
40+
$ bundle install
41+
```
42+
43+
For reasons discussed below, our CI builds avoid loading Bundler at runtime
44+
by using Bundler's [`--standalone option`](http://myronmars.to/n/dev-blog/2012/03/faster-test-boot-times-with-bundler-standalone).
45+
While not strictly necessary (many/most of our contributors do not do this!),
46+
if you want to exactly reproduce our CI builds you'll want to do the same:
47+
48+
```
49+
$ bundle install --standalone --binstubs
50+
```
51+
52+
The `--binstubs` option creates the `bin/rspec` file that, like `bundle exec rspec`, will load
53+
all the versions specified in `Gemfile.lock` without loading bundler at runtime!
54+
55+
## Gotcha: Version mismatch from sibling repos
56+
57+
The [../Gemfile] is designed to be flexible and support using
58+
the other RSpec repositories either from a local sibling directory
59+
(e.g. `../rspec-<subproject>`) or, if there is no such directory,
60+
directly from git. This generally does the "right thing", but can
61+
be a gotcha in some situations. For example, if you are setting up
62+
`rspec-core`, and you happen to have an old clone of `rspec-expectations`
63+
in a sibling directory, it'll be used even though it might be months or
64+
years out of date, which can cause confusing failures.
65+
66+
To avoid this problem, you can either `export USE_GIT_REPOS=1` to force
67+
the use of `:git` dependencies instead of local dependencies, or update
68+
the code in the sibling directory. rspec-dev contains rake tasks to
69+
help you keep all repos in sync.
70+
71+
## Extra Gems
72+
73+
If you need additional gems for any tasks---such as `benchmark-ips` for benchmarking
74+
or `byebug` for debugging---you can create a `Gemfile-custom` file containing those
75+
gem declarations. The `Gemfile` evaluates that file if it exists, and it is git-ignored.
76+
77+
# Running the build
78+
79+
The [Travis CI build](https://travis-ci.org/rspec/<%= project_name %>)
80+
runs many verification steps to prevent regressions and
81+
ensure high-quality code. To run the Travis build locally, run:
82+
83+
```
84+
$ script/run_build
85+
```
86+
87+
# What to Expect
88+
89+
To ensure high, uniform code quality, all code changes (including
90+
changes from the maintainers!) are subject to a pull request code
91+
review. We'll often ask for clarification or suggest alternate ways
92+
to do things. Our code reviews are intended to be a two-way
93+
conversation.
94+
95+
While every user-facing change needs a changelog entry, don't worry
96+
about adding it yourself. Since the changelog changes to frequently,
97+
it tends to be the source of merge conflicts when contributors include
98+
edits in their PRs, so we prefer to add changelog entries ourselves
99+
after merging your PR.
100+
101+
# Adding Docs
102+
103+
RSpec uses [YARD](http://yardoc.org/) for its API documentation. To
104+
ensure the docs render well, we recommend running a YARD server and
105+
viewing your edits in a browser.
106+
107+
To run a YARD server:
108+
109+
```
110+
$ bundle exec yard server --reload
111+
112+
# or, if you installed your bundle with `--standalone --binstubs`:
113+
114+
$ bin/yard server --reload
115+
```
116+
117+
Then navigate to `localhost:8808` to view the rendered docs.
118+
119+
# The CI build, in detail
120+
121+
As mentioned above, RSpec runs many verification steps as part of its CI build.
122+
Let's break this down into the individual steps.
123+
124+
## Specs
125+
126+
RSpec dogfoods itself. It's primary defense against regressions is its spec suite. Run with:
127+
128+
```
129+
$ bundle exec rspec
130+
131+
# or, if you installed your bundle with `--standalone --binstubs`:
132+
133+
$ bin/rspec
134+
```
135+
136+
The spec suite performs a couple extra checks that are worth noting:
137+
138+
* *That all the code is warning-free.* Any individual example that produces output
139+
to `stderr` will fail. We also have a spec that loads all the `lib` and `spec`
140+
files in a newly spawned process to detect load-time warnings and fail if there
141+
are any. RSpec must be warning-free so that users who enable Ruby warnings will
142+
not get warnings from our code.
143+
* *That only a minimal set of stdlibs are loaded.* Since Ruby makes loaded libraries
144+
available for use in any context, we want to minimize how many bits of the standard
145+
library we load and use. Otherwise, RSpec's use of part of the standard library could
146+
mask a problem where a gem author forgets to load a part of the standard library they
147+
rely on. The spec suite contains a spec that defines a whitelist of allowed loaded
148+
stdlibs.
149+
150+
In addition, we use [SimpleCov](https://github.com/colszowka/simplecov)
151+
to measure and enforce test coverage. If the coverage falls below a
152+
project-specific threshold, the build will fail.
153+
154+
## Cukes
155+
156+
RSpec uses [cucumber](https://cucumber.io/) for both acceptance testing and [documentation](https://relishapp.com/rspec). Run with:
157+
158+
```
159+
$ bundle exec cucumber
160+
161+
# or, if you installed your bundle with `--standalone --binstubs`:
162+
163+
$ bin/cucumber
164+
```
165+
166+
## YARD documentation
167+
168+
RSpec uses [YARD](http://yardoc.org/) for API documentation on the [rspec.info site](http://rspec.info/).
169+
Our commitment to [SemVer](htp://semver.org) requires that we explicitly
170+
declare our public API, and our build uses YARD to ensure that every
171+
class, module and method has either been labeled `@private` or has at
172+
least some level of documentation. For new APIs, this forces us to make
173+
an intentional decision about whether or not it should be part of
174+
RSpec's public API or not.
175+
176+
To run the YARD documentation coverage check, run:
177+
178+
```
179+
$ bundle exec yard stats --list-undoc
180+
181+
# or, if you installed your bundle with `--standalone --binstubs`:
182+
183+
$ bin/yard stats --list-undoc
184+
```
185+
186+
We also want to prevent YARD errors or warnings when actually generating
187+
the docs. To check for those, run:
188+
189+
```
190+
$ bundle exec yard doc --no-cache
191+
192+
# or, if you installed your bundle with `--standalone --binstubs`:
193+
194+
$ bin/yard doc --no-cache
195+
```
196+
197+
## Rubocop
198+
199+
We use [Rubocop](https://github.com/bbatsov/rubocop) to enforce style conventions on the project so
200+
that the code has stylistic consistency throughout. Run with:
201+
202+
```
203+
$ bundle exec rubocop lib
204+
205+
# or, if you installed your bundle with `--standalone --binstubs`:
206+
207+
$ bin/rubocop lib
208+
```
209+
210+
Our Rubocop configuration is a work-in-progress, so if you get a failure
211+
due to a Rubocop default, feel free to ask about changing the
212+
configuration. Otherwise, you'll need to address the Rubocop failure,
213+
or, as a measure of last resort, by wrapping the offending code in
214+
comments like `# rubocop:disable SomeCheck` and `# rubocop:enable SomeCheck`.
215+
216+
## Run spec files one-by-one
217+
218+
A fast TDD cycle depends upon being able to run a single spec file,
219+
without the rest of the test suite. While rare, it's fairly easy to
220+
create a situation where a spec passes when the entire suite runs
221+
but fails when its individual file is run. To guard against this,
222+
our CI build runs each spec file individually, using a bit of bash like:
223+
224+
```
225+
for file in `find spec -iname '*_spec.rb'`; do
226+
echo "Running $file"
227+
bin/rspec $file -b --format progress
228+
done
229+
```
230+
231+
Since this step boots RSpec so many times, it runs much, much
232+
faster when we can avoid the overhead of bundler. This is a main reason our
233+
CI build installs the bundle with `--standalone --binstubs` and
234+
runs RSpec via `bin/rspec` rather than `bundle exec rspec`.
235+
236+
## Running the spec suite for each of the other repos
237+
238+
While each of the RSpec repos is an independent gem (generally designed
239+
to be usable on its own), there are interdependencies between the gems,
240+
and the specs for each tend to use features from the other gems. We
241+
don't want to merge a pull request for one repo that might break the
242+
build for another repo, so our CI build includes a spec that runs the
243+
spec suite of each of the _other_ project repos. Note that we only run
244+
the spec suite, not the full build, of the other projects, as the spec
245+
suite runs very quickly compared to the full build.
246+

0 commit comments

Comments
 (0)