backspin 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +3 -1
  3. data/CHANGELOG.md +4 -0
  4. data/CLAUDE.md +6 -6
  5. data/CONTRIBUTING.md +3 -5
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +2 -2
  8. data/README.md +113 -34
  9. data/backspin.gemspec +2 -2
  10. data/bin/rake +27 -0
  11. data/bin/rspec +27 -0
  12. data/fixtures/backspin/all_mode_filter.yml +14 -0
  13. data/fixtures/backspin/credential_filter.yml +18 -0
  14. data/fixtures/backspin/echo_hello.yml +14 -0
  15. data/fixtures/backspin/echo_verify.yml +14 -0
  16. data/fixtures/backspin/episodes_filter.yml +26 -0
  17. data/fixtures/backspin/failure_test.yml +14 -0
  18. data/fixtures/backspin/full_data_filter.yml +17 -0
  19. data/fixtures/backspin/mixed_calls.yml +24 -0
  20. data/fixtures/backspin/multi_command.yml +34 -0
  21. data/fixtures/backspin/multi_command_filter.yml +26 -0
  22. data/fixtures/backspin/multi_field_filter.yml +13 -0
  23. data/fixtures/backspin/multi_system.yml +20 -0
  24. data/fixtures/backspin/nil_filter.yml +14 -0
  25. data/fixtures/backspin/none_mode_test.yml +14 -0
  26. data/fixtures/backspin/path_test.yml +17 -0
  27. data/fixtures/backspin/playback_system.yml +12 -0
  28. data/fixtures/backspin/playback_test.yml +14 -0
  29. data/fixtures/backspin/stderr_test.yml +19 -0
  30. data/fixtures/backspin/system_echo.yml +12 -0
  31. data/fixtures/backspin/system_false.yml +18 -0
  32. data/fixtures/backspin/timestamp_test.yml +18 -0
  33. data/fixtures/backspin/use_record_filter.yml +15 -0
  34. data/fixtures/backspin/verify_system.yml +12 -0
  35. data/fixtures/backspin/verify_system_diff.yml +11 -0
  36. data/fixtures/backspin/version_test.yml +14 -0
  37. data/lib/backspin/command.rb +33 -14
  38. data/lib/backspin/command_diff.rb +88 -0
  39. data/lib/backspin/command_result.rb +60 -0
  40. data/lib/backspin/record.rb +2 -2
  41. data/lib/backspin/record_result.rb +153 -0
  42. data/lib/backspin/recorder.rb +4 -23
  43. data/lib/backspin/version.rb +1 -1
  44. data/lib/backspin.rb +169 -287
  45. metadata +33 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9afcbf90256cbfd84f6b9694544282dc593fc715d9886a9e3a9ba54e064410fc
4
- data.tar.gz: c3d6e95547f27364b4108b5f75641ed88a9e153f0e4ccdbed3d276e82dd5f99b
3
+ metadata.gz: f44a53c1983fd41c2660bc9652c158b2193e880e0e1339fa49c882d26fdd0852
4
+ data.tar.gz: 3b53d9ba92db35ad66c128bc049762e06c307472827fe2d4b795427c7e668bdf
5
5
  SHA512:
6
- metadata.gz: 2c7c36cee5518f0944896c04c96d36ae134d56928510ee01aef646a2eb0c036c723ab65aff64c6726751ce6b4c406de90f486e4da5bd3242344fd23d8e7792f1
7
- data.tar.gz: 116e28fadefdc8651f648f25f0da4c347d86127448a34e0ca20a244f6bb0e7f101e140052e0f0e9029ec1693b40b6363ab3d7db6a0b7c2a0ab9252976ae64c33
6
+ metadata.gz: 28909c63f9befbe8a0ae208328b9c527b3f1ca28417a66e96afad6ee9be41c2fa157ede63e4c5073f049ac59ab9c336a5fde7b97e109b7efc61480942ddc1a58
7
+ data.tar.gz: e63c8c4fff6ac690575ffadfe48efd6b4d0bc2267680e1c99637a888edcf3034bb315d96efedc400bfabdf5f8a9aa7912dfef03771b86a6a69769efe1bdcaac6
data/.circleci/config.yml CHANGED
@@ -7,6 +7,7 @@ orbs:
7
7
 
8
8
  jobs:
9
9
  build:
10
+ resource_class: medium
10
11
  parameters:
11
12
  ruby-version:
12
13
  type: string
@@ -15,7 +16,8 @@ jobs:
15
16
 
16
17
  steps:
17
18
  - checkout
18
- - ruby/install-deps
19
+ - ruby/install-deps:
20
+ key: gems-v1-ruby<< parameters.ruby-version >>
19
21
  - run:
20
22
  name: Run specs and lint
21
23
  command: bundle exec rake
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.0] - 2025-06-06
4
+
5
+ Simpler, unified API: `Backspin.run` and `Backspin run!` methods that automatically record on first use and verify on subsequent runs. `run!` will raise an error if results differ, whereas `run` will return the result for the caller to decide what to do with
6
+
3
7
  ## [0.3.0] - 2025-06-05
4
8
  - Scrub credentials from command arguments
5
9
 
data/CLAUDE.md CHANGED
@@ -17,14 +17,14 @@ bin/setup
17
17
  ### Testing
18
18
  ```bash
19
19
  bin/rake spec # Run all tests
20
- rspec spec/[file] # Run specific test file
21
- rspec spec/[file]:[line] # Run specific test
20
+ bin/rspec spec/[file] # Run specific test file
21
+ bin/rspec spec/[file]:[line] # Run specific test
22
22
  ```
23
23
 
24
24
  ### Building and Releasing
25
25
  ```bash
26
- bundle exec rake install # Install gem locally for testing
27
- bundle exec rake release # Release to RubyGems (updates version, tags, pushes)
26
+ bin/rake install # Install gem locally for testing
27
+ bin/rake release # Release to RubyGems (updates version, tags, pushes)
28
28
  ```
29
29
 
30
30
  ### Code Quality
@@ -62,7 +62,7 @@ bin/rake standard # Run Standard Ruby linter
62
62
  ### Testing Approach
63
63
 
64
64
  - Integration-focused tests that exercise the full stack
65
- - Default record directory is `spec/backspin_data` (can be configured)
65
+ - Default record directory is `fixtures/backspin` (can be configured)
66
66
  - Tests use real shell commands (`echo`, `date`, etc.)
67
67
  - Configuration is reset between tests to avoid side effects
68
68
  - **Important**: Backspin specs MUST be as local and un-DRY as possible. Each spec should be self-contained with its own setup, expectations, and cleanup if needed. Avoid shared contexts or helpers that hide important test details.
@@ -76,7 +76,7 @@ bin/rake standard # Run Standard Ruby linter
76
76
  4. Run tests with `rake spec`
77
77
 
78
78
  ### Debugging Tests
79
- - Records are saved to `spec/backspin_data/` by default
79
+ - Records are saved to `fixtures/backspin/` by default
80
80
  - Check YAML files to see recorded command outputs
81
81
 
82
82
  ### Updating Credential Patterns
data/CONTRIBUTING.md CHANGED
@@ -99,7 +99,7 @@ Backspin is a Ruby gem for characterization testing of command-line interfaces.
99
99
 
100
100
  #### Debugging Tests
101
101
 
102
- - Records are saved to `spec/backspin_data/` by default
102
+ - Records are saved to `fixtures/backspin/` by default
103
103
  - Check YAML files to see recorded command outputs
104
104
 
105
105
  ## Testing
@@ -125,7 +125,7 @@ Backspin uses integration-focused tests that exercise the full stack. When writi
125
125
  - Avoid shared contexts or helpers that hide important test details
126
126
  - Use real shell commands (`echo`, `date`, etc.) for testing
127
127
  - Ensure configuration is reset between tests to avoid side effects
128
- - Verify new or updated test records in `spec/backspin_data/`
128
+ - Verify new or updated test records in `fixtures/backspin/`
129
129
 
130
130
  Example test structure:
131
131
 
@@ -161,7 +161,6 @@ end
161
161
 
162
162
  - Keep changes focused and atomic
163
163
  - Include tests for new functionality
164
- - Maintain backward compatibility when possible
165
164
  - Update examples in README.md if changing public APIs
166
165
  - Ensure CI passes (tests against Ruby 3.2, 3.3, and 3.4)
167
166
 
@@ -203,8 +202,7 @@ We welcome feature requests! When proposing new features:
203
202
  1. Check existing issues to avoid duplicates
204
203
  2. Describe the use case and motivation
205
204
  3. Provide code examples of how the feature would work
206
- 4. Consider backward compatibility
207
- 5. Be open to discussion and alternative approaches
205
+ 4. Be open to discussion and alternative approaches
208
206
 
209
207
  ## Additional Resources
210
208
 
data/Gemfile CHANGED
@@ -7,5 +7,5 @@ group :development do
7
7
  gem "rake", "~> 13.0"
8
8
  gem "rspec", "~> 3.0"
9
9
  gem "timecop", "~> 0.9"
10
- gem "standard", "~> 1.0"
10
+ gem "standard"
11
11
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- backspin (0.3.0)
4
+ backspin (0.4.1)
5
5
  ostruct (~> 0.5.0)
6
6
  rspec-mocks (~> 3.0)
7
7
 
@@ -80,7 +80,7 @@ DEPENDENCIES
80
80
  backspin!
81
81
  rake (~> 13.0)
82
82
  rspec (~> 3.0)
83
- standard (~> 1.0)
83
+ standard
84
84
  timecop (~> 0.9)
85
85
 
86
86
  BUNDLED WITH
data/README.md CHANGED
@@ -1,8 +1,13 @@
1
- # Backspin   [![Gem Version](https://badge.fury.io/rb/backspin.svg)](https://badge.fury.io/rb/backspin) [![CircleCI](https://dl.circleci.com/status-badge/img/gh/rsanheim/backspin/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/rsanheim/backspin/tree/main)
1
+ # Backspin
2
2
 
3
- Backspin records and replays CLI interactions in Ruby for easy snapshot testing of command-line interfaces. Currently supports `Open3.capture3` and `system` and requires `rspec-mocks`. More system calls and flexible test integration are welcome - PRs welcome!
3
+ [![Ruby](https://img.shields.io/badge/ruby-%23CC342D.svg?style=flat&logo=ruby&logoColor=white)](https://www.ruby-lang.org/)
4
+ [![Gem Version](https://img.shields.io/gem/v/backspin)](https://rubygems.org/gems/backspin)
5
+ [![CircleCI](https://img.shields.io/circleci/build/github/rsanheim/backspin/main)](https://circleci.com/gh/rsanheim/backspin)
6
+ [![Last Commit](https://img.shields.io/github/last-commit/rsanheim/backspin/main)](https://github.com/rsanheim/backspin/commits/main)
4
7
 
5
- **NOTE:** Backspin is in early development (version 0.2.x), and you can expect the API to change. It is being developed along-side in-production CLI apps, so the API will be refined and improved as we get to 1.0.
8
+ Backspin records and replays CLI interactions in Ruby for easy snapshot testing of command-line interfaces. Currently supports `Open3.capture3` and `system` and requires `rspec-mocks`. More system calls and test integrations are welcome - send a PR!
9
+
10
+ **NOTE:** Backspin should be considered alpha quality software while pre v1.0. It is in heavy development, and you can expect the API to change. It is being developed in conjunction with production CLI apps, so the API will be refined and improved as we get to 1.0.
6
11
 
7
12
  Inspired by [VCR](https://github.com/vcr/vcr) and other [golden master](https://en.wikipedia.org/wiki/Golden_master_(software_development)) libraries.
8
13
 
@@ -24,73 +29,147 @@ And then run `bundle install`.
24
29
 
25
30
  ## Usage
26
31
 
27
- ### Recording CLI interactions
32
+ ### Quick Start
33
+
34
+ The simplest way to use Backspin is with the `run` method, which automatically records on the first execution and verifies on subsequent runs:
28
35
 
29
36
  ```ruby
30
- require "backspin"
37
+ require "backspin"
38
+
39
+ # First run: records the output
40
+ result = Backspin.run("my_command") do
41
+ Open3.capture3("echo hello world")
42
+ end
31
43
 
32
- # Record a command's output
33
- result = Backspin.call("echo_hello") do
34
- stdout, stderr, status = Open3.capture3("echo hello")
35
- # This will save the output to `spec/backspin_data/echo_hello.yaml`.
44
+ # Subsequent runs: verifies the output matches
45
+ result = Backspin.run("my_command") do
46
+ Open3.capture3("echo hello world")
36
47
  end
37
48
 
49
+ # Use run! to automatically fail tests on mismatch
50
+ Backspin.run!("my_command") do
51
+ Open3.capture3("echo hello mars")
52
+ end
53
+ # Raises an error because stdout will not match the recorded output
38
54
  ```
39
55
 
40
- ### Verifying CLI output
56
+ ### Recording Modes
57
+
58
+ Backspin supports different modes for controlling how commands are recorded and verified:
41
59
 
42
60
  ```ruby
43
- # Verify that a command produces the expected output
44
- result = Backspin.verify("echo_hello") do
61
+ # Auto mode (default): Record on first run, verify on subsequent runs
62
+ result = Backspin.run("my_command") do
63
+ Open3.capture3("echo hello")
64
+ end
65
+
66
+ # Explicit record mode: Always record, overwriting existing recordings
67
+ result = Backspin.run("echo_test", mode: :record) do
45
68
  Open3.capture3("echo hello")
46
69
  end
70
+ # This will save the output to `fixtures/backspin/echo_test.yml`.
47
71
 
72
+ # Explicit verify mode: Always verify against existing recording
73
+ result = Backspin.run("echo_test", mode: :verify) do
74
+ Open3.capture3("echo hello")
75
+ end
48
76
  expect(result.verified?).to be true
77
+
78
+ # Playback mode: Return recorded output without running the command
79
+ result = Backspin.run("slow_command", mode: :playback) do
80
+ Open3.capture3("slow_command") # Not executed - returns recorded output
81
+ end
49
82
  ```
50
83
 
51
- ### Using verify! for automatic test failures
84
+ ### Using run! for automatic test failures
85
+
86
+ The `run!` method works exactly like `run` but automatically fails the test if verification fails:
52
87
 
53
88
  ```ruby
54
89
  # Automatically fail the test if output doesn't match
55
- Backspin.verify!("echo_hello") do
90
+ Backspin.run!("echo_test") do
56
91
  Open3.capture3("echo hello")
57
92
  end
93
+ # Raises an error with detailed diff if verification fails from recorded data in "echo_test.yml"
58
94
  ```
59
95
 
60
- ### Playback mode for fast tests
96
+ ### Custom matchers
97
+
98
+ For cases where exact matching isn't suitable, you can provide custom verification logic:
61
99
 
62
100
  ```ruby
63
- # Return recorded output without running the command
64
- result = Backspin.verify("slow_command", mode: :playback) do
65
- Open3.capture3("slow_command") # Not executed - will playback from the record yaml (assuming it exists)
101
+ # Use custom logic to verify output
102
+ result = Backspin.run("version_check",
103
+ matcher: ->(recorded, actual) {
104
+ # Just check that both start with "ruby"
105
+ recorded["stdout"].start_with?("ruby") &&
106
+ actual["stdout"].start_with?("ruby")
107
+ }) do
108
+ Open3.capture3("ruby --version")
66
109
  end
67
110
  ```
68
111
 
69
- ### Custom matchers
112
+ ### Working with the Result Object
113
+
114
+ The API returns a `RecordResult` object with helpful methods:
70
115
 
71
116
  ```ruby
72
- # Use custom logic to verify output
73
- Backspin.verify("version_check",
74
- matcher: ->(recorded, actual) {
75
- # Just check that both start with "ruby"
76
- recorded["stdout"].start_with?("ruby") &&
77
- actual["stdout"].start_with?("ruby")
78
- }) do
79
- Open3.capture3("ruby --version")
117
+ result = Backspin.run("my_test") do
118
+ Open3.capture3("echo out; echo err >&2; exit 42")
80
119
  end
120
+
121
+ # Check the mode
122
+ result.recorded? # true on first run
123
+ result.verified? # true/false on subsequent runs, nil when recording
124
+ result.playback? # true in playback mode
125
+
126
+ # Access output (first command for single commands)
127
+ result.stdout # "out\n"
128
+ result.stderr # "err\n"
129
+ result.status # 42
130
+ result.success? # false (non-zero exit)
131
+ result.output # The raw return value from the block
132
+
133
+ # Debug information
134
+ result.record_path # Path to the YAML file
135
+ result.error_message # Human-readable error if verification failed
136
+ result.diff # Diff between expected and actual output
81
137
  ```
82
138
 
83
- ### VCR-style use_record
139
+ ### Multiple Commands
84
140
 
85
- _The plan is to make something like this the main entry point API for ease of use_
141
+ Backspin automatically records and verifies all commands executed in a block:
86
142
 
87
143
  ```ruby
88
- # Record on first run, replay on subsequent runs
89
- Backspin.use_record("my_command", record: :once) do
90
- Open3.capture3("echo hello")
144
+ result = Backspin.run("multi_command_test") do
145
+ # All of these commands will be recorded
146
+ version, = Open3.capture3("ruby --version")
147
+ files, = Open3.capture3("ls -la")
148
+ system("echo 'Processing...'") # Note: system doesn't capture output
149
+ data, stderr, = Open3.capture3("curl https://api.example.com/data")
150
+
151
+ # Return whatever you need
152
+ { version: version.strip, file_count: files.lines.count, data: data }
91
153
  end
154
+
155
+ # Access individual command results
156
+ result.commands.size # 4
157
+ result.multiple_commands? # true
158
+
159
+ # For multiple commands, use these accessors
160
+ result.all_stdout # Array of stdout from each command
161
+ result.all_stderr # Array of stderr from each command
162
+ result.all_status # Array of exit statuses
163
+
164
+ # Or access specific commands
165
+ result.commands[0].stdout # Ruby version output
166
+ result.commands[1].stdout # ls output
167
+ result.commands[2].status # system call exit status (stdout is empty)
168
+ result.commands[3].stderr # curl errors if any
92
169
  ```
93
170
 
171
+ When verifying multiple commands, Backspin ensures all commands match in the exact order they were recorded. If any command differs, you'll get a detailed error showing which commands failed.
172
+
94
173
  ### Credential Scrubbing
95
174
 
96
175
  If the CLI interaction you are recording contains sensitive data in stdout or stderr, you should be careful to make sure it is not recorded to yaml!
@@ -102,7 +181,7 @@ A tool like [trufflehog](https://github.com/trufflesecurity/trufflehog) or [gitl
102
181
 
103
182
  ```ruby
104
183
  # This will automatically scrub AWS keys, API tokens, passwords, etc.
105
- Backspin.call("aws_command") do
184
+ Backspin.run("aws_command") do
106
185
  Open3.capture3("aws s3 ls")
107
186
  end
108
187
 
@@ -146,4 +225,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/rsanhe
146
225
 
147
226
  ## License
148
227
 
149
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
228
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/backspin.gemspec CHANGED
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
20
20
  spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
21
21
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
22
22
  end
23
- spec.bindir = "bin"
24
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.bindir = "exe"
24
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
25
25
  spec.require_paths = ["lib"]
26
26
 
27
27
  spec.add_dependency "rspec-mocks", "~> 3.0"
data/bin/rake ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("rake", "rake")
data/bin/rspec ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rspec' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("rspec-core", "rspec")
@@ -0,0 +1,14 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Open3::Capture3
6
+ args:
7
+ - echo
8
+ - "'second'"
9
+ stdout: 'filtered output 2
10
+
11
+ '
12
+ stderr: ''
13
+ status: 0
14
+ recorded_at: '2025-05-01T12:00:00Z'
@@ -0,0 +1,18 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Open3::Capture3
6
+ args:
7
+ - echo
8
+ - "'My"
9
+ - API
10
+ - key
11
+ - is
12
+ - "********************'"
13
+ stdout: 'MY API KEY IS ********************
14
+
15
+ '
16
+ stderr: ''
17
+ status: 0
18
+ recorded_at: '2025-05-01T12:00:00Z'
@@ -0,0 +1,14 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Open3::Capture3
6
+ args:
7
+ - echo
8
+ - hello
9
+ stdout: 'hello
10
+
11
+ '
12
+ stderr: ''
13
+ status: 0
14
+ recorded_at: '2025-05-01T12:00:00Z'
@@ -0,0 +1,14 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Open3::Capture3
6
+ args:
7
+ - echo
8
+ - hello
9
+ stdout: 'hello
10
+
11
+ '
12
+ stderr: ''
13
+ status: 0
14
+ recorded_at: '2025-05-01T12:00:00Z'
@@ -0,0 +1,26 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Open3::Capture3
6
+ args:
7
+ - echo
8
+ - "'episode"
9
+ - 1'
10
+ stdout: 'EPISODE 1
11
+
12
+ '
13
+ stderr: ''
14
+ status: 0
15
+ recorded_at: '2025-05-01T12:00:00Z'
16
+ - command_type: Open3::Capture3
17
+ args:
18
+ - echo
19
+ - "'episode"
20
+ - 2'
21
+ stdout: 'EPISODE 2
22
+
23
+ '
24
+ stderr: ''
25
+ status: 0
26
+ recorded_at: '2025-05-01T12:00:00Z'
@@ -0,0 +1,14 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Open3::Capture3
6
+ args:
7
+ - echo
8
+ - expected
9
+ stdout: 'expected
10
+
11
+ '
12
+ stderr: ''
13
+ status: 0
14
+ recorded_at: '2025-05-01T12:00:00Z'
@@ -0,0 +1,17 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Open3::Capture3
6
+ args:
7
+ - bash
8
+ - "-c"
9
+ - echo 'stdout message' && echo 'stderr message' >&2 && exit 42
10
+ stdout: 'stdout message
11
+
12
+ '
13
+ stderr: 'stderr message
14
+
15
+ '
16
+ status: 42
17
+ recorded_at: '2025-05-01T12:00:00Z'
@@ -0,0 +1,24 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Kernel::System
6
+ args:
7
+ - echo
8
+ - from
9
+ - system
10
+ stdout: ''
11
+ stderr: ''
12
+ status: 0
13
+ recorded_at: '2025-05-01T12:00:00Z'
14
+ - command_type: Open3::Capture3
15
+ args:
16
+ - echo
17
+ - from
18
+ - capture3
19
+ stdout: 'from capture3
20
+
21
+ '
22
+ stderr: ''
23
+ status: 0
24
+ recorded_at: '2025-05-01T12:00:00Z'
@@ -0,0 +1,34 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Open3::Capture3
6
+ args:
7
+ - echo
8
+ - first
9
+ stdout: 'first
10
+
11
+ '
12
+ stderr: ''
13
+ status: 0
14
+ recorded_at: '2025-05-01T12:00:00Z'
15
+ - command_type: Open3::Capture3
16
+ args:
17
+ - echo
18
+ - second
19
+ stdout: 'second
20
+
21
+ '
22
+ stderr: ''
23
+ status: 0
24
+ recorded_at: '2025-05-01T12:00:00Z'
25
+ - command_type: Open3::Capture3
26
+ args:
27
+ - echo
28
+ - third
29
+ stdout: 'third
30
+
31
+ '
32
+ stderr: ''
33
+ status: 0
34
+ recorded_at: '2025-05-01T12:00:00Z'
@@ -0,0 +1,26 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Open3::Capture3
6
+ args:
7
+ - echo
8
+ - "'Count:"
9
+ - 42'
10
+ stdout: 'Count: X
11
+
12
+ '
13
+ stderr: ''
14
+ status: 0
15
+ recorded_at: '2025-05-01T12:00:00Z'
16
+ - command_type: Open3::Capture3
17
+ args:
18
+ - echo
19
+ - "'Total:"
20
+ - 100'
21
+ stdout: 'Total: X
22
+
23
+ '
24
+ stderr: ''
25
+ status: 0
26
+ recorded_at: '2025-05-01T12:00:00Z'
@@ -0,0 +1,13 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Open3::Capture3
6
+ args:
7
+ - bash
8
+ - "-c"
9
+ - echo 'out' && echo 'err' >&2 && exit 1
10
+ stdout: modified stdout
11
+ stderr: modified stderr
12
+ status: 0
13
+ recorded_at: '2025-05-01T12:00:00Z'
@@ -0,0 +1,20 @@
1
+ ---
2
+ first_recorded_at: '2025-05-01T12:00:00Z'
3
+ format_version: '2.0'
4
+ commands:
5
+ - command_type: Kernel::System
6
+ args:
7
+ - echo
8
+ - first
9
+ stdout: ''
10
+ stderr: ''
11
+ status: 0
12
+ recorded_at: '2025-05-01T12:00:00Z'
13
+ - command_type: Kernel::System
14
+ args:
15
+ - echo
16
+ - second
17
+ stdout: ''
18
+ stderr: ''
19
+ status: 0
20
+ recorded_at: '2025-05-01T12:00:00Z'