Unit Testing ROT13 Implementations

Write comprehensive unit tests for a ROT13 function. Cover edge cases including empty strings, non-alpha characters, mixed case, double application, and Unicode.

Programming

Detailed Explanation

Testing ROT13 Implementations

A ROT13 function seems simple, but thorough testing requires covering many edge cases. Here is a comprehensive test suite.

Core Test Cases

describe('rot13', () => {
  // Basic functionality
  test('encodes lowercase letters', () => {
    expect(rot13('hello')).toBe('uryyb');
  });

  test('encodes uppercase letters', () => {
    expect(rot13('HELLO')).toBe('URYYB');
  });

  test('preserves mixed case', () => {
    expect(rot13('Hello World')).toBe('Uryyb Jbeyq');
  });
});

Self-Reciprocal Property

test('double application returns original', () => {
  const original = 'The Quick Brown Fox';
  expect(rot13(rot13(original))).toBe(original);
});

test('double application on all printable ASCII', () => {
  const all = Array.from({ length: 95 }, (_, i) =>
    String.fromCharCode(32 + i)
  ).join('');
  expect(rot13(rot13(all))).toBe(all);
});

Edge Cases

test('empty string returns empty', () => {
  expect(rot13('')).toBe('');
});

test('digits pass through unchanged', () => {
  expect(rot13('abc123def')).toBe('nop123qrs');
});

test('punctuation and spaces unchanged', () => {
  expect(rot13('Hello, World!')).toBe('Uryyb, Jbeyq!');
});

test('single character boundary: a and z', () => {
  expect(rot13('a')).toBe('n');
  expect(rot13('z')).toBe('m');
  expect(rot13('A')).toBe('N');
  expect(rot13('Z')).toBe('M');
});

test('boundary: m and n', () => {
  expect(rot13('m')).toBe('z');
  expect(rot13('n')).toBe('a');
  expect(rot13('M')).toBe('Z');
  expect(rot13('N')).toBe('A');
});

Non-English Characters

test('non-ASCII letters pass through unchanged', () => {
  expect(rot13('café')).toBe('pnsé');  // é is not shifted
  expect(rot13('naïve')).toBe('anïir'); // ï is not shifted
});

test('emoji pass through unchanged', () => {
  expect(rot13('hello 👋')).toBe('uryyb 👋');
});

test('CJK characters pass through', () => {
  expect(rot13('hello世界')).toBe('uryyb世界');
});

Property-Based Testing

For maximum confidence, use property-based testing:

test.prop('rot13 is an involution', [fc.string()], (s) => {
  expect(rot13(rot13(s))).toBe(s);
});

test.prop('length is preserved', [fc.string()], (s) => {
  expect(rot13(s).length).toBe(s.length);
});

test.prop('non-alpha chars unchanged', [fc.string()], (s) => {
  const nonAlpha = s.replace(/[a-zA-Z]/g, '');
  const encoded = rot13(s).replace(/[a-zA-Z]/g, '');
  expect(encoded).toBe(nonAlpha);
});

Use Case

Comprehensive ROT13 test suites are used in programming courses to teach test-driven development, edge case thinking, and property-based testing. They also serve as practical examples when demonstrating testing frameworks like Jest, Vitest, or pytest.

Try It — ROT13 / Caesar Cipher

Open full tool