Skip to content

14 — Tooling, testing and gems

One line: The machinery around a Ruby program — loading files, gems and Bundler, Minitest, the command line, irb, the release history, backtraces and the missing docstring — measured against Python's import, pip, unittest, python3 -i, traceback and __doc__.

A Python programmer arrives with a working model of all of this: import runs a module once and caches it in sys.modules; pip and a venv hold the packages a project needs and pyproject.toml declares them; unittest is a TestCase class with assert* methods; the >>> prompt echoes values; traceback and inspect read the stack; every function has a __doc__. Most of that model carries over with the names changed — require for import, $LOADED_FEATURES for sys.modules, gem/bundle for pip, Gemfile for the dependency list, Minitest::Test for TestCase, irb for the prompt, caller and backtrace for the stack.

Where it breaks is the interesting part. Ruby has three loading verbs to Python's one (require, require_relative, load) plus autoload; RubyGems can activate a gem version at run time, which import cannot; Minitest runs tests in a seeded random order and, as of Ruby 4.0's Minitest 6, no longer ships Minitest::Mock; the -I, -s and -S flags mean different things in the two interpreters; the Ruby prompt echoes assignments and defs because they are expressions; backtrace labels are Klass#method strings; and there is no docstring at all — a method knows only its source_location, and documentation is a comment convention that RDoc, YARD and ri read from the file.

Lesson Level The one thing
require loads once; load runs every time 201 require and require_relative share one once-list, load ignores it, autoload defers
Gems are versioned; Bundler pins them 201 default gems, bundled gems and core classes are three different things; Gem::Version compares as numbers
A Minitest test is a plain class 201 the seeded, shuffled run and its runs, assertions, failures, errors, skips line, next to unittest
The command line is part of the language 201 -e -c -w -r -I -n -p -a -l -E --yjit --disable-gems --dump, each run in a child and compared with python3's letters
irb echoes every value; a script does not 101 the read–eval–print loop driven through a pipe, values only, beside python3 -i and code.InteractiveConsole
What changed, 1.9 to 4.0 201 a timeline table, and a program that checks which of its features this Ruby and this Python have
A backtrace is data you can read 201 caller, caller_locations, backtrace, full_message as labels, next to traceback and inspect
Ruby has no docstrings 101 source_location plus the comment above the def, read from the file, next to __doc__ and inspect.getcomments

Read more