Files
ubicloud/.by-session-setup.rb
Jeremy Evans b3cf8d685c Add rake by for faster testing of single file or spec
One of the most common developer operations when developing a new
feature is running a single test related to that feature.  As ubicloud
uses rspec, generally that takes the form of `rspec file:line`. When
you run `rspec file:line`, it needs to load all ruby libraries
necessary to run that particular spec, which can take much more time
than running the spec itself.  For example:

```
$ time rspec spec/model/nic_spec.rb:7
Run options: include {:locations=>{"./spec/model/nic_spec.rb"=>[7]}}

Randomized with seed 54633

Nic
  ubid_to_name
    returns name from ubid

Top 1 slowest examples (0.00289 seconds, 3.5% of total time):
  Nic ubid_to_name returns name from ubid
    0.00289 seconds ./spec/model/nic_spec.rb:7

Finished in 0.08183 seconds (files took 0.90238 seconds to load)
1 example, 0 failures

Randomized with seed 54633

real    0m1.361s
user    0m1.074s
sys     0m0.191s
```

We see here that it takes 1.36 seconds to run this rspec command,
of which 0.90 seconds were spent loading files, and only 0.08 seconds
were spent running the spec.

Most of the time spent loading files is actually spent loading
libraries required by files.  Since those libraries should be
unchanged until you have updated your Gemfile, one strategy for
speeding up running a single spec is preloading all libraries
into a Ruby process, and then using that Ruby process (or a fork
of it) to execute the spec.  That approach is implemented by "by".

To speed up the above running of a single spec, you first run
`rake by`, which will open up a new shell.  Inside that shell,
you then append `by` before rspec:

```
$ time by rspec spec/model/nic_spec.rb:7
Run options: include {:locations=>{"./spec/model/nic_spec.rb"=>[7]}}

Randomized with seed 64910

Nic
  ubid_to_name
    returns name from ubid

Top 1 slowest examples (0.00293 seconds, 4.8% of total time):
  Nic ubid_to_name returns name from ubid
    0.00293 seconds ./spec/model/nic_spec.rb:7

Finished in 0.06144 seconds (files took 0.12752 seconds to load)
1 example, 0 failures

Randomized with seed 64910

real    0m0.579s
user    0m0.275s
sys     0m0.056s
```

You can see that this drops total execution time from 1.36 seconds to
0.58 seconds, because the time to load files drops from 0.90 seconds
to 0.13 seconds.

How this works is that `rake by` calls `by-session`.  `by-session`
creates a `by-server` process that loads `.by-session-setup.rb`,
That file loads all libraries in the Gemfile, as well as as any
extensions/plugins/other files used by libraries, which are not
loaded by requiring the library itself.  After the `by-server`
process is created, `by-session` spawns a shell that supports `by`.
Running `by` inside the subshell connects to the server process,
providing the arguments, environment, stdin/stdout/stderr, and the
current directory.  The server process forks, sets up ENV, reopens
stdin/stdout/stderr, changes to the directory in which you called
`by`, and operates on the arguments given.  If the first argument
to `by` is `rspec`, then `by` will operate similarly to `rspec`.

This currently uses the master branch of `by`, because rspec support
was just added to `by` (to support this feature in ubicloud), and is
not yet in a released version.

This will require some minor additional maintenance going forward. As
there are new files loaded by the specs, beyond what would be loaded
by the Gemfile, those will need to be added to `.by-session-setup.rb.
2024-10-24 06:01:19 -07:00

6.1 KiB