Back to Repositories

Validating Grammar Definitions and Submodule Configuration in github-linguist

This test suite validates the integrity and synchronization of grammar definitions in the linguist repository. It ensures proper scope management, submodule configuration, and documentation consistency for language grammar specifications.

Test Coverage Overview

The test suite provides comprehensive coverage of grammar-related functionality:

Key areas tested include:
  • Duplicate scope detection in grammars.yml
  • Submodule synchronization verification
  • README documentation accuracy
  • HTTPS compliance for submodule links

Implementation Analysis

The testing approach utilizes Ruby’s Minitest framework with a focus on configuration validation. The implementation follows a structured pattern of loading YAML configurations, verifying file system states, and checking repository integrity through git commands.

Notable patterns include:
  • YAML configuration parsing
  • Git submodule management
  • File system path validation
  • Documentation synchronization checks

Technical Details

Testing tools and configuration:
  • Minitest test framework
  • YAML for grammar definitions
  • Git submodule commands
  • File system operations
  • Regular expressions for path matching

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolated test setup using setup method
  • Clear error messages with detailed instructions
  • Comprehensive validation of external dependencies
  • Maintainable test organization with private helper methods
  • Documentation-as-code validation

github-linguist/linguist

test/test_grammars.rb

            
require_relative "./helper"

class TestGrammars < Minitest::Test
  ROOT = File.expand_path("../..", __FILE__)

  def setup
    @grammars = YAML.load(File.read(File.join(ROOT, "grammars.yml")))
  end

  def test_no_duplicate_scopes
    scopes = @grammars.values.flatten
    duplicates = scopes.group_by { |s| s }.select { |k, v| v.length > 1 }.map(&:first)
    assert duplicates.empty?, "The following scopes appear in grammars.yml more than once:
#{duplicates.sort.join("
")}"
  end

  def test_submodules_are_in_sync
    # Strip off paths inside the submodule so that just the submodule path remains.
    listed_submodules = @grammars.keys.grep(/vendor\/grammars/).map { |source| source[%r{vendor/grammars/[^/]+}] }

    nonexistent_submodules = listed_submodules - submodule_paths
    unlisted_submodules = submodule_paths - listed_submodules

    message = ""
    unless nonexistent_submodules.empty?
      message << "The following submodules are listed in grammars.yml but don't seem to exist in the repository.
"
      message << "Either add them using `git submodule add` or remove them from grammars.yml.
"
      message << nonexistent_submodules.sort.join("
")
    end
    unless unlisted_submodules.empty?
      message << "
" unless message.empty?
      message << "The following submodules exist in the repository but aren't listed in grammars.yml.
"
      message << "Either add them to grammars.yml or remove them from the repository using `git rm`.
"
      message << unlisted_submodules.sort.join("
")
    end

    assert nonexistent_submodules.empty? && unlisted_submodules.empty?, message.sub(/\.\Z/, "")
  end

  def test_readme_file_is_in_sync
    current_data = File.read("#{ROOT}/vendor/README.md").to_s.sub(/\A.+?<!--.+?-->
/mu, "")
    updated_data = `script/list-grammars --print`
    assert_equal current_data, updated_data, "Grammar list is out-of-date. Run `script/list-grammars`"
  end

  def test_submodules_use_https_links
    File.open(".gitmodules", "r") do |fh|
      ssh_submodules = []
      fh.each_line do |line|
        if matches = line.match(/url = (git@.*)/)
          submodule_link = matches.captures[0]
          ssh_submodules.push(submodule_link)
        end
      end
      msg = "The following submodules don't have an HTTPS link:
* #{ssh_submodules.join("
* ")}"
      assert_equal [], ssh_submodules, msg
    end
  end

  private

  def submodule_paths
    @submodule_paths ||= `git config --list --file "#{File.join(ROOT, ".gitmodules")}"`.lines.grep(/\.path=/).map { |line| line.chomp.split("=", 2).last }.reject { |path| path =~ /CodeMirror/ }
  end

end