Jekyll Bug Fix with Matt Series Index
- Part 0: Series Introduction
- Part 1: How Matt found this perfectly-suited issue to fix
- Part 2: Setting up the app locally, writing a failing test you are here
- Part 3: Making that failing test pass! š
- Part 4: Making the Pull Request
Part 2 Table of Contents
This is the third part of a short series on pairing with a super-experienced software developer to fix an open-source issue in Jekyll.
In the last post, Matt explained how he identified this particular issue for us to work on.
This series (and more series in the future) will constantly attempt to surface the tacit knowledge that experienced developers use to do their work.
How to read this particular post #
Remember, the goal of this entire series is for you to do the exact same things an expert does.
How to follow along with us #
To follow along, in your local environment, youāll need to clone down the repo, and check out a commit from before our fix gets merged.
Since youāre not necessarily making your own PR, you donāt have to fork it to your own repo, you can just clone it. Hereās how to set it up:
// get the repo
$ git clone git@github.com:jekyll/jekyll.git
// now check out from the same commit Matt and I were working with:
$ git checkout 8403184b
Now youāve got the codebase in the same place we had it in!
Open up the Contribution Guidelines and work through the video with us! The Jekyll docs talk about the various scripts we used here
Video Walkthrough #
Video Timestamps #
- 0:00 Talking about what setup Matt has done (almost none!)
- 0:40 Jekyll contribution docs: https://jekyllrb.com/docs/contributing/
- 0:48 Looking for
CONTRIBUTING.markdown
in project - 1:15 Running tests locally, running scripts (we start with
script/bootstrap
) - 1:35 exploring script directory, running recommended scripts
- 2:00 how to execute scripts in the shell
- 2:45 Looking at GH Issue for clue of what file to start with
- 3:05 #1 keyboard shortcut to know:
Fuzzy-finder/go-to-file
- 3:30 ārun tests for current fileā - Iāve never used this extension, but Iāve also never used .NET or Java.
- 4:40 installing all the gems takes FOREVER
- 4:53 Matt does some amazing keyboard work to do something specific, quickly.
- 5:32 reading the method in question, starting to figure out what it does, what jumps out at Matt
- 6:36 quick
select-find-jump
usage to jump around file - 8:15 the bootstrap script is finished, finally!
- 9:00 still exploring relationship between
Utils#slugify
andUtils#replace_character_sequence_with_hyphen
- 10:00 āweāre getting warmerā with finding what to pay attention to, what to ignore
- 11:20 explaining what I18n means, and a16z, not mentioned but commonly seen: a11y => āaccessibilityā
- 12:40 Matt supposing that #slugify probably changes a lot. Itās āa hotspotā.
- 13:40 Matt searches for slugify, then .slugify.
- 15:38 Running ./script/cibuild, 2nd script recommended in contribution guidelines. (because the first script finally finished)
- 16:30 Matt explains how he found the file to add the test too
- 18:29 splitting tabs, test on one side, lib on the other. (SEE NOTES FOR FURTHER THOUGHTS ON SPLITTING PANES)
- 19:40 Matt mentions that this repo is in his /junk folder š
- 20:10 Checking out a new branch! š
- 20:23 Odd issue where git was picking up test artifacts. Must have been a temporary file.
- 21:27 Figuring out how to run an individual test file
- 21:57 What test framework ARE we using? Looking at script/test
- 22:53 Running just the test_utils.rb file.
- 23:40 Talking about test output, how overwhelming this all is!
- 24:04 What is the āoptions āseedā thing?
- 25:51 Expounding on test coverage, timing, understanding the ātimeā output (real vs. user vs. system)
- 26:50 āthe only thing that is of minor use to useā¦ is the test coverage percentageā
- 28:55 Figuring out WHERE to put our new test.
- 30:16 Narrowing down to the ā#slugifyā context block
- 31:10 Starting to actually add lines of code. š©āš»
- 31:33 copying from the test below to get our basic test
- 31:48 copying expected/actual values from @deepestblueās issue (thanks again, @deepestblue, for such a good bug report)
- 32:44 running the file again, this time expecting a failure. And getting it! šššš
Expanding on things that came up in the video: #
Running scripts per the contribution guidelines #
The Jekyll Contribution Guidelines specifies running a certain script (script/boostrap
) to kick off all the tests.
This means thereās a directory of scripts (appropriately lableled script
, which presumably has many scripts, but we care about only one of them. boostrap
)
To execute a script, you have to prepend it with ./
. This will tell your operating system that you do indeed intend on running the given script.
So, Matt runs the script with:
$ ./script/boostrap
and that runs under the hood something like:
bundle install
While it installs, Matt and I talk about a next iteration of this project that might involve work on dev.to
. Itās more of an application than a library (Jekyll is a library) so it might be a bit more relevant to the day-to-day of the normal software developer.
Shipping a library for your day job is different than working on an application.
As Iāve mentioned, one of the goals of this project is to find instances where the expert uses Tacit Knowledge. Iāll use this section to bring attention to as much of Mattās tacit knowledge as possible.
Top keyboard shortcut for Atom/VS Code #
Matt says āthe top two shortcutsā¦ā
- fuzzy finder (Atom, VS Code)
- run test file for current file (Josh needs to find this, requires a plugin)
For ārun tests for current fileā I usually want to look at the test file before running it, so my workflow is:
- use fuzzy finder to open up the desired test file
- Use keyboard shortcut to copy the relative path of the test file to my clipboard. Atom:
shift+ctrl+c
- Run the test file in whatever method the project requires:
ruby <file>
,bundle exec ruby -Itest <file>
,./test <file>
, etc.
copy-find-paste-enter
keyboard shortcuts #
keyboard shortcuts! Matt uses this one all the time, and if youāre not using this keyboard shortcut, might be time to start.
This file weāre looking at is 350+ lines long. Scrolling up and down is a waste of time.
Hereās what he does:
- Double-click the method name or constant he wants to jump to.
- hit
ā+c
to copy it to his clipboard - hit
ā+f
to open thefind in current file
tool. - Hit
ā+v
to paste the clipboard contents into the search box - hit
return
on his keyboard to jump to the top result. Hitting enter repeatedly cycles through all the instances of the string in the file.
This isnāt just fast, but allows him to not waste thought trying to find bits of code, or scroll around. He doesnāt care where in the file a constant or method is defined, just wants to look at it.
Please add this general process to your own workflow, if itās not already there.
Note - When youāre staying inside the editor, at least for Atom, I can double-click any text, and when I hit ā+f
Atom inserts the selected string in the search box. This saves me a copy/paste.
Jargon: I18N (internationalization) #
i18n
, a16z
, a11y
are all phrases you might have come accros in the industry.
i18n
=>internationalization
(there are 18 letters between thei
and then
)a16z
=>AndreessenHorowitz
(there are 16 letters between thea
and thez
)a11y
=>accessibility
(there are 11 letters between thea
and they
)
Running another script (cibuild
) #
Runs rubocop, the unit tests.
The Jekyll team has confidence in the build setup, so we run the tests to make sure weāre starting in a clean state.
Splitting panes horizontally vs. vertically #
Add screenshots here, mention being able to see lots of test output at the same time
Matt says
Usually I split my panes verticallyā¦
Hereās why. Look at the line counts:
With the keyboard shortcut of ā+\
, you can toggle the visibility of the sidebar effortlessly.
If instead we split the screens horizontally, hereās what weād get:
Matt splits the panes horizontally, since heās running his fonts unsually large so they come through better in the recording.
How Matt decided which file to add the failing test to #
Searching for slugify
vs. .slugify
Ah, the file name convention is different from what I expected.
I expected {class_under_test}_test.rb
, but itās actually test_{class_under_test}.rb
Try this yourself, in your editor of choice. Do you see the difference in results?
Keybindings #
Matt has keyboard shortcuts set up for his commonly used applications.
I noticed that I donāt think he used alt-tab once.
Iāve got keyboard shortcuts set up for Atom
, Firefox
, iTerm
, and a few other tools. I hardly ever use alt+tab
on my laptop, and it feels like this saves time and effort.
Iām all for copying what experts do, might be worth setting something similar up on your own machine.
Iāve written extensively about exactly how I have my āenvironmentā set up here
Writing the first test #
At about an hour in, weāve written three lines of code:
# test/test_utils.rb:140
it 'should not break certain tamil characters' do
assert_equal "ą®®ą®²ąÆą®²ą®æą®ŖąÆą®ŖąÆ-ą®µą®ąÆą®ą®³ąÆ", Utils.slugify("ą®®ą®²ąÆą®²ą®æą®ŖąÆą®ŖąÆ ą®µą®ąÆą®ą®³ąÆ")
end
Checks for Understanding #
- When prepping to do open-source work, should you fork the repo before cloning it?
- What script should we run that, according to the Jekyll docs, makes sure the project is set up and running correctly?
- How do you run a script? What directory would we expect scripts to be in?
- Why would you run a script?
- What 2 things does
./script/bootstrap
do? - Whatās the keyboard shortcut for opening
go-to-file
/fuzzy-finder
for your editor? - What script would we use to make sure the repo is in good shape to work with? Hint:
CircleCI
runs against every new PR. What does this script do? - What script do you use to run tests?
- How would you find every spot that
slugify
is mentioned? How about every time the method is called? - What does the
test_utils
script do? - What are the implications of Jekyllās test coverage? (Itās 64%).
- How would we run tests for just the
lib/jekyll/utils.rb
file? - When you add the first test, what should the
assert_equals
arguments be? (Hint: they come from the Jekyll issue report)
Next, jump over to part 3.
But before you go, why not subscribe to get updates when more guides in this series are done, as well as when future guides go up?