Back to Repositories

Testing Shell Package Generation and Script Execution in jordansissel/fpm

This test suite validates the shell package functionality in FPM (Effing Package Management), focusing on script execution and package structure verification. The tests ensure proper handling of installation scripts and package segment organization.

Test Coverage Overview

The test suite provides comprehensive coverage of shell package generation and execution in FPM.

Key areas tested include:
  • Pre-installation script execution validation
  • Empty script handling
  • Package segment verification
  • Archive and metadata presence checks
The suite particularly focuses on BASH shell compatibility and proper package structure generation.

Implementation Analysis

The testing approach utilizes RSpec’s context-based structure to organize related test scenarios logically. The implementation employs temporary file handling and directory management for isolated testing environments.

Notable patterns include:
  • Helper method abstraction for package creation
  • Environment-aware test skipping
  • Shell command execution verification
  • File content validation

Technical Details

Testing tools and configuration:
  • RSpec as the testing framework
  • Tempfile for temporary file management
  • Dir.mktmpdir for temporary directory creation
  • Environment variable checking for BASH shell detection
  • Script execution validation through system commands

Best Practices Demonstrated

The test suite exemplifies several testing best practices for package management systems.

Notable practices include:
  • Proper test isolation using temporary resources
  • Environmental awareness and graceful degradation
  • Comprehensive setup and teardown procedures
  • Clear test organization using describe and context blocks
  • Effective error case handling

jordansissel/fpm

spec/fpm/package/sh_spec.rb

            
require "spec_setup"
require "fpm" # local
require "fpm/package/sh" # local
require "tmpdir"

shell_is_bash = (%r{/bash} =~ ENV['SHELL'])
if !shell_is_bash
  Cabin::Channel.get("rspec").warn("Skipping SH pkg tests which require a BASH shell.")
end

describe FPM::Package::Sh do
  describe "#output" do
    before do
      skip("Shell (SHELL env) is not bash") unless shell_is_bash
    end

    def make_sh_package
      # output a package, use it as the input, set the subject to that input
      # package. This helps ensure that we can write and read packages
      # properly.
      tmpfile = Tempfile.new("fpm-test-sh")
      target = tmpfile.path
      # The target file must not exist.
      tmpfile.unlink

      original = FPM::Package::Sh.new
      yield original if block_given?
      original.output(target)

      return target, original
    end
    context "pre_install script" do
      before :all do
        @temptarget = Dir.mktmpdir()
        @target, @original = make_sh_package do |pkg|
          pkg.scripts[:before_install] = "#!/bin/sh\n\necho before_install"
        end
      end
      it "should execute a pre_install script" do
        output = `#{@target} -i #{@temptarget}`.split($/)
        insist { output.any? {|l| l.chomp == "before_install" }} == true
        insist { $?.success? } == true
      end
    end
    context "empty pre_install script" do
      before :all do
        @temptarget = Dir.mktmpdir()
        @target, @original = make_sh_package do |pkg|
          pkg.scripts[:before_install] = ""
        end
      end
      it "shouldn't choke even if the pre-install script is empty" do
        output = %x(#{@target} -i #{@temptarget})
        status = $?.success?
        insist { status } == true
      end
    end

    context "Contain segments" do
      before :all do
        @target, @original = make_sh_package
      end

      after :all do
        @original.cleanup
      end # after

      context "package contents" do
        it "should contain a ARCHIVE segment" do
          insist { File.readlines(@target).any? {|l| l.chomp == '__ARCHIVE__' } } == true
        end

        it "should contain a METADATA segment" do
          insist { File.readlines(@target).any? {|l| l.chomp == '__METADATA__' } } == true
        end
      end # package attributes
    end
  end # #output
end # describe FPM::Package::Sh