Mutation Testing in xlsxrb

To verify test assertion strength and avoid tests that execute code without asserting behavior, xlsxrb adopts mutation testing via mbj/mutant with test-unit integration.

As of the current release, the test suite achieves 100.00% kill rate (1,091 / 1,091 mutations killed, 0 alive) across all 38 pure functional subjects.

Motivation & Strategy

Standard code coverage measures whether lines of code were executed during tests. However, it cannot guarantee that the tests will fail if the codeโ€™s behavior is altered or corrupted. Mutation testing systematically modifies source code (introducing โ€œmutantsโ€ such as flipping conditionals, substituting constants, or removing statements) and checks whether existing tests catch the mutation (โ€œkillโ€ the mutant).

Targeted Scope: Functional Core, Pure Predicates & Byte Encoding

Running mutation testing across the entire codebase (which includes heavy file I/O, ZIP streaming, and large XML parsing) is computationally expensive and prone to creating brittle tests for streaming writers. Therefore, xlsxrb follows the functional core / imperative shell architecture, focusing mutation testing on pure functions, boundary predicates, coordinate conversions, and binary encoders:

  1. Coordinates & Cell Conversions (Xlsxrb::Elements::Cell, CoordinateAccess):

  2. Column letters to 0-based indices ("A" โ†” 0, "Z" โ†” 25, "AA" โ†” 26, up to "XFD" โ†” 16383).

  3. Pure predicate checks (Cell.valid_coordinates?, Cell.valid_value?, Cell#valid?).

  4. String, integer, and float conversions (Cell#to_s, Cell#to_i, Cell#to_f, Cell#content, Cell#ref).

  5. Coordinate access references and cell sorting (CoordinateAccess#cells, CoordinateAccess#[]).

  6. Worksheet, Column, Row & Workbook Invariants (Xlsxrb::Elements::*, Xlsxrb::StreamRow):

  7. Worksheet name validation (Worksheet.valid_name? with 1..31 characters and forbidden character rules \ / ? * [ ]).

  8. Column and row bounds (Column.valid_index?, Column.validate, Column#valid?, Row.valid_index?, Row#valid?).

  9. Workbook structure validation (Workbook#valid?).

  10. Streaming row data integrity (StreamRow#valid?, StreamRow#unmapped_data, StreamRow#errors, StreamRow#values).

  11. Serial Value & DateTime Conversions (Xlsxrb::Ooxml::Utils):

  12. Julian Day โ†” 1900-based serial number conversions (date_to_serial, serial_to_date).

  13. Time fractions and fractional days arithmetic (datetime_to_serial, serial_to_datetime).

  14. Excel 1900 leap year bug handling.

  15. Binary Parsing & Bitfield Packings (Xlsxrb::Ooxml::ZipGenerator, Xlsxrb::Ooxml::Cfb):

  16. Little-endian 16/32-bit byte serialization (ZipGenerator.le16, ZipGenerator.le32).

  17. MS-DOS packed datetime calculation with arithmetic bitfield combinations (ZipGenerator.dos_datetime).

  18. Compound File Binary (CFB) magic header recognition (Cfb::Reader.cfb?) and directory entry predicates (DirEntry#stream?, #root?, #storage?).

  19. XML Character Escaping (Xlsxrb::Ooxml::XmlBuilder):

  20. Pure escaping of XML special characters (XmlBuilder.escape) with object identity preservation for clean strings.

  21. DSL Normalization (Xlsxrb::DslHelpers):

  22. Column indices, range, and alphabet normalization (DslHelpers.normalize_column_indices).

Excluded Scope (Non-Targets)

Running Mutation Testing

# Run full mutation testing suite (38 subjects, ~35 seconds)
bundle exec rake mutant:pure

# Or run mutant against a specific class or method using .mutant.yml configuration
bundle exec mutant run -- 'Xlsxrb::Elements::Cell.valid_value?'