Testing
Test Structure
Tests are organized by component:
spec/
├── spec_helper.rb
├── archive_spec.rb
├── cli_spec.rb
├── file_magic_spec.rb
├── extractors/
│ ├── cab_extractor_spec.rb
│ ├── zip_extractor_spec.rb
│ └── ...
└── fixtures/
├── test.zip
├── test.tar.gz
└── ...Writing Tests
Basic Structure
RSpec.describe Excavate::Archive do
describe '#extract' do
let(:archive) { 'spec/fixtures/test.zip' }
let(:target) { Dir.mktmpdir }
it 'extracts archive to target' do
described_class.new(archive).extract(target)
expect(Dir.glob("#{target}/*")).not_to be_empty
end
end
endFixtures
Test archives are in spec/fixtures/:
spec/fixtures/
├── test.zip # Basic ZIP
├── test.tar # Basic TAR
├── test.tar.gz # Compressed TAR
├── test.cab # CAB archive
├── test.msi # MSI installer
├── nested.zip # Archive with nested archive
└── empty.zip # Empty archiveTest Patterns
Testing Extraction
it 'extracts all files' do
archive = described_class.new(fixture_path)
archive.extract(target)
files = Dir.glob("#{target}/**/*").select { |f| File.file?(f) }
expect(files.size).to be > 0
endTesting Recursive Extraction
it 'extracts nested archives recursively' do
archive = described_class.new(msi_path)
archive.extract(target, recursive_packages: true)
# Should not contain .cab files
cabs = Dir.glob("#{target}/**/*.cab")
expect(cabs).to be_empty
# Should contain extracted files
expect(Dir.glob("#{target}/**/*")).not_to be_empty
endCLI Testing
describe Excavate::CLI do
def run_cli(*args)
output = StringIO.new
$stdout = output
begin
described_class.start(args)
ensure
$stdout = STDOUT
end
output.string
end
it 'extracts archive' do
result = run_cli('extract', fixture_path)
expect(result).to include('Successfully extracted')
end
endBest Practices
-
Isolation: Each test should be independent
-
Cleanup: Clean up temp files after tests
-
Speed: Keep tests fast
-
Readability: Use descriptive names
-
Coverage: Test edge cases and errors