ShellStone

February 4, 2026 ยท View on GitHub

A cross-platform testing framework for Smalltalk inspired by RSpec.

Table of Contents

Installation

Pharo

Metacello new
  baseline: 'ShellStone';
  repository: 'github://tomas-stefano/shellstone:main/pharo-src';
  load.

GNU Smalltalk

git clone https://github.com/tomas-stefano/shellstone.git
cd shellstone
make gnu-install

Quick Start

Pharo

Sh describe: 'Calculator' do: [ :spec |
  spec it: 'adds two numbers' do: [
    (Sh expect: 1 + 1) to equal: 2
  ].

  spec it: 'multiplies numbers' do: [
    (Sh expect: 3 * 4) to equal: 12
  ]
].

GNU Smalltalk

Namespace current: ShellStone [

Describe the: 'Calculator' do: [:spec |
  spec it: 'adds two numbers' do: [
    (self expect: 1 + 1) to equal: 2.
  ].

  spec it: 'multiplies numbers' do: [
    (self expect: 3 * 4) to equal: 12.
  ].
].

]

GNU Smalltalk

Expectation Syntax

ShellStone supports two syntaxes: expect (recommended) and should (legacy).

"Expect syntax (recommended)"
(self expect: actual) to matcher.
(self expect: actual) toNot matcher.

"Should syntax (legacy)"
actual should matcher.
actual shouldNot matcher.

Structure

Describe the: 'MyClass' do: [:spec |
  spec context: 'when initialized' do: [:ctx |
    ctx it: 'has default values' do: [
      (self expect: MyClass new value) to equal: 0.
    ].
  ].
].

Hooks

Describe the: 'Database' do: [:spec |
  | connection |

  spec before: #each do: [
    connection := Database connect.
  ].

  spec after: #each do: [
    connection close.
  ].

  spec it: 'queries data' do: [
    (self expect: (connection query: 'SELECT 1')) toNot beNil.
  ].
].

Test Doubles

"Doubles"
db := ShellStone.Double named: 'database'.
db stub: #find: andReturn: 'user'.
(self expect: (db find: 1)) to equal: 'user'.

"Spies"
list := OrderedCollection new.
spy := ShellStone.Spy on: list.
spy add: 1.
spy add: 2.
(self expect: (spy received: #add: times: 2)) to beTrue.

Running Tests

bin/shellstone           # Run specs
make gnu-spec            # Run specs via make
make gnu-spec-doc        # Documentation format

Pharo

DSL Entry Point

All DSL entry points go through the Sh class:

Sh describe: 'Calculator' do: [ :spec |
  spec it: 'adds two numbers' do: [
    (Sh expect: 1 + 1) to equal: 2
  ]
].

Test Doubles

"Doubles"
db := Sh double: 'database'.
db stub: #find: andReturn: 'user'.
(Sh expect: (db find: 1)) to equal: 'user'.

"Spies"
list := OrderedCollection new.
spy := Sh spyOn: list.
spy add: 1.
(Sh expect: (spy received: #add:)) to beTrue.

Running Tests

# Via make (auto-downloads Pharo)
make pharo-spec
PHARO_VERSION=110 make pharo-spec

# Via Pharo CLI
./pharo Pharo.image shellstone
./pharo Pharo.image shellstone --help

Matchers Reference

MatcherExample
equal:(Sh expect: 1) to equal: 1
beA: / beAn:(Sh expect: 'hi') to beA: String
beKindOf:(Sh expect: 42) to beKindOf: Number
beTrue / beFalse(Sh expect: true) to beTrue
beTruthy / beFalsy(Sh expect: 1) to beTruthy
beNil(Sh expect: nil) to beNil
beGreaterThan:(Sh expect: 10) to beGreaterThan: 5
beLessThan:(Sh expect: 5) to beLessThan: 10
beGreaterThanOrEqualTo:(Sh expect: 5) to beGreaterThanOrEqualTo: 5
beLessThanOrEqualTo:(Sh expect: 5) to beLessThanOrEqualTo: 5
include:(Sh expect: #(1 2 3)) to include: 2
match:(Sh expect: 'hello') to match: 'ell'
respondTo:(Sh expect: 'hi') to respondTo: #size
raiseError(Sh expect: [1/0]) to raiseError
raiseError:(Sh expect: [1/0]) to raiseError: ZeroDivide
change:(Sh expect: [x := x + 1]) to change: [x]

All matchers support negation with toNot (or shouldNot in GNU Smalltalk).


CLI

GNU Smalltalk

bin/shellstone                    # Run specs in current directory
bin/shellstone spec/              # Run specs in specific directory

Pharo

./pharo Pharo.image shellstone           # Run specs
./pharo Pharo.image shellstone --help    # Show help
./pharo Pharo.image shellstone --version # Show version

Development

Make Commands

make                # Run all specs (GNU + Pharo)
make gnu-spec       # GNU Smalltalk specs
make pharo-spec     # Pharo specs
make clean          # Remove tmp/
make help           # Show all commands

Adding New Files

For GNU Smalltalk, edit package.xml:

<filein>gnu-src/your/new_file.st</filein>

For Pharo, add classes to pharo-src/ in Tonel format.

License

MIT