【Sphinx】unittestを使った、IndexEntries.create_index()の振る舞いの確認

unittestを使った、IndexEntries.create_index()の振る舞いの確認。

テストデータとその結果から、Sphinxがどのようにソート処理をしているのかが見えてくる。

# 環境

- Windows10/cygwin64
- Python 3.8.10
- Sphinx 4.2.0

このテストの通るバージョンは索引データについては、4.2.0と互換性がることになる。

# unittest_IndexEntries.py

```python
#!/usr/bin/python
import unittest
from sphinx.environment.adapters.indexentries import IndexEntries


#正規表現による字句解析
testcase1 = [
{   #テストパターン
    'doc3': [
        ('single','あああ','id-311','',None),
        ('single','ううう','id-313','main',None),
        ('single','おおお','id-315','',None),
        ('single','あああ','id-316','main',None),
        ('single','ううう','id-318','',None),
        ('single','おおお','id-310','main',None),
        ('pair','あああ; かかか','id-321','',None),
        ('pair','ううう; くくく','id-323','main',None),
        ('pair','おおお; こここ','id-325','',None),
        ('pair','あああ; かかか','id-326','main',None),
        ('pair','ううう; くくく','id-328','',None),
        ('pair','おおお; こここ','id-320','main',None),
        ('triple','あああ; かかか; さささ','id-331','',None),
        ('triple','ううう; くくく; すすす','id-333','main',None),
        ('triple','おおお; こここ; そそそ','id-335','','分類'),
        ('triple','あああ; かかか; さささ','id-336','main',None),
        ('triple','ううう; くくく; すすす','id-338','',None),
        ('triple','おおお; こここ; そそそ','id-330','main',None),
        ('single','あああ; かかか','id-341','',None),
        ('single','ううう; くくく','id-343','main',None),
        ('single','おおお; こここ','id-345','',None),
        ('single','あああ; かかか','id-346','main',None),
        ('single','ううう; くくく','id-348','',None),
        ('single','おおお; こここ','id-340','main',None),
    ],
    'doc1': [
        ('single','おおお; こここ','id-140','main',None),
        ('single','ううう; くくく','id-148','main',None),
        ('single','あああ; かかか','id-146','main',None),
        ('single','あああ; かかか','id-141','',None),
        ('triple','おおお; こここ; そそそ','id-130','main',None),
        ('triple','ううう; くくく; すすす','id-138','main','分類'),
        ('triple','あああ; かかか; さささ','id-136','main',None),
        ('triple','おおお; こここ; そそそ','id-135','',None),
        ('triple','ううう; くくく; すすす','id-133','',None),
        ('triple','あああ; かかか; さささ','id-131','','分類'),
        ('pair','おおお; こここ','id-120','main',None),
        ('pair','ううう; くくく','id-128','main',None),
        ('pair','あああ; かかか','id-126','main',None),
        ('pair','おおお; こここ','id-125','','分類'),
        ('pair','ううう; くくく','id-123','',None),
        ('pair','あああ; かかか','id-121','',None),
        ('single','おおお','id-110','main',None),
        ('single','ううう','id-118','main','分類'),
        ('single','あああ','id-116','main',None),
        ('single','おおお','id-115','',None),
        ('single','ううう','id-113','',None),
        ('single','あああ','id-111','','分類'),
        ('single','ううう; くくく','id-143','',None),
        ('single','おおお; こここ','id-145','','分類'),
    ],
    'doc2': [
        ('single','おおお','id-215','',None),
        ('single','ううう','id-213','',None),
        ('single','あああ','id-211','','分類'),
        ('single','あああ','id-216','main',None),
        ('single','ううう','id-218','main','分類'),
        ('single','おおお','id-210','main',None),
        ('pair','おおお; こここ','id-225','','分類'),
        ('pair','ううう; くくく','id-223','',None),
        ('pair','あああ; かかか','id-221','',None),
        ('pair','おおお; こここ','id-220','main',None),
        ('pair','ううう; くくく','id-228','main',None),
        ('pair','あああ; かかか','id-226','main',None),
        ('triple','おおお; こここ; そそそ','id-235','',None),
        ('triple','ううう; くくく; すすす','id-233','',None),
        ('triple','あああ; かかか; さささ','id-231','','分類'),
        ('triple','あああ; かかか; さささ','id-236','main',None),
        ('triple','ううう; くくく; すすす','id-238','main','分類'),
        ('triple','おおお; こここ; そそそ','id-230','main',None),
        ('single','おおお; こここ','id-245','','分類'),
        ('single','ううう; くくく','id-243','',None),
        ('single','あああ; かかか','id-241','',None),
        ('single','あああ; かかか','id-246','main',None),
        ('single','ううう; くくく','id-248','main',None),
        ('single','おおお; こここ','id-240','main',None),
    ],
},
  #想定する結果
  [('あ',
    [('あああ',
      [[('main', 'doc1.html#id-116'),
        ('main', 'doc2.html#id-216'),
        ('main', 'doc3.html#id-316'),
        ('', 'doc1.html#id-111'),
        ('', 'doc2.html#id-211'),
        ('', 'doc3.html#id-311')],
       [('かかか',
         [('main', 'doc1.html#id-126'),
          ('main', 'doc1.html#id-146'),
          ('main', 'doc2.html#id-226'),
          ('main', 'doc2.html#id-246'),
          ('main', 'doc3.html#id-326'),
          ('main', 'doc3.html#id-346'),
          ('', 'doc1.html#id-121'),
          ('', 'doc1.html#id-141'),
          ('', 'doc2.html#id-221'),
          ('', 'doc2.html#id-241'),
          ('', 'doc3.html#id-321'),
          ('', 'doc3.html#id-341')]),
        ('かかか さささ',
         [('main', 'doc1.html#id-136'),
          ('main', 'doc2.html#id-236'),
          ('main', 'doc3.html#id-336'),
          ('', 'doc1.html#id-131'),
          ('', 'doc2.html#id-231'),
          ('', 'doc3.html#id-331')])],
       None])]),
   ('う',
    [('ううう',
      [[('main', 'doc1.html#id-118'),
        ('main', 'doc2.html#id-218'),
        ('main', 'doc3.html#id-313'),
        ('', 'doc1.html#id-113'),
        ('', 'doc2.html#id-213'),
        ('', 'doc3.html#id-318')],
       [('くくく',
         [('main', 'doc1.html#id-128'),
          ('main', 'doc1.html#id-148'),
          ('main', 'doc2.html#id-228'),
          ('main', 'doc2.html#id-248'),
          ('main', 'doc3.html#id-323'),
          ('main', 'doc3.html#id-343'),
          ('', 'doc1.html#id-123'),
          ('', 'doc1.html#id-143'),
          ('', 'doc2.html#id-223'),
          ('', 'doc2.html#id-243'),
          ('', 'doc3.html#id-328'),
          ('', 'doc3.html#id-348')]),
        ('くくく すすす',
         [('main', 'doc1.html#id-138'),
          ('main', 'doc2.html#id-238'),
          ('main', 'doc3.html#id-333'),
          ('', 'doc1.html#id-133'),
          ('', 'doc2.html#id-233'),
          ('', 'doc3.html#id-338')])],
       None])]),
   ('お',
    [('おおお',
      [[('main', 'doc1.html#id-110'),
        ('main', 'doc2.html#id-210'),
        ('main', 'doc3.html#id-310'),
        ('', 'doc1.html#id-115'),
        ('', 'doc2.html#id-215'),
        ('', 'doc3.html#id-315')],
       [('こここ',
         [('main', 'doc1.html#id-120'),
          ('main', 'doc1.html#id-140'),
          ('main', 'doc2.html#id-220'),
          ('main', 'doc2.html#id-240'),
          ('main', 'doc3.html#id-320'),
          ('main', 'doc3.html#id-340'),
          ('', 'doc1.html#id-125'),
          ('', 'doc1.html#id-145'),
          ('', 'doc2.html#id-225'),
          ('', 'doc2.html#id-245'),
          ('', 'doc3.html#id-325'),
          ('', 'doc3.html#id-345')]),
        ('こここ そそそ',
         [('main', 'doc1.html#id-130'),
          ('main', 'doc2.html#id-230'),
          ('main', 'doc3.html#id-330'),
          ('', 'doc1.html#id-135'),
          ('', 'doc2.html#id-235'),
          ('', 'doc3.html#id-335')])],
       None])]),
   ('か',
    [('かかか',
      [[],
       [('あああ',
         [('main', 'doc1.html#id-126'),
          ('main', 'doc2.html#id-226'),
          ('main', 'doc3.html#id-326'),
          ('', 'doc1.html#id-121'),
          ('', 'doc2.html#id-221'),
          ('', 'doc3.html#id-321')]),
        ('さささ, あああ',
         [('main', 'doc1.html#id-136'),
          ('main', 'doc2.html#id-236'),
          ('main', 'doc3.html#id-336'),
          ('', 'doc1.html#id-131'),
          ('', 'doc2.html#id-231'),
          ('', 'doc3.html#id-331')])],
       None])]),
   ('く',
    [('くくく',
      [[],
       [('ううう',
         [('main', 'doc1.html#id-128'),
          ('main', 'doc2.html#id-228'),
          ('main', 'doc3.html#id-323'),
          ('', 'doc1.html#id-123'),
          ('', 'doc2.html#id-223'),
          ('', 'doc3.html#id-328')]),
        ('すすす, ううう',
         [('main', 'doc1.html#id-138'),
          ('main', 'doc2.html#id-238'),
          ('main', 'doc3.html#id-333'),
          ('', 'doc1.html#id-133'),
          ('', 'doc2.html#id-233'),
          ('', 'doc3.html#id-338')])],
       None])]),
   ('こ',
    [('こここ',
      [[],
       [('おおお',
         [('main', 'doc1.html#id-120'),
          ('main', 'doc2.html#id-220'),
          ('main', 'doc3.html#id-320'),
          ('', 'doc1.html#id-125'),
          ('', 'doc2.html#id-225'),
          ('', 'doc3.html#id-325')]),
        ('そそそ, おおお',
         [('main', 'doc1.html#id-130'),
          ('main', 'doc2.html#id-230'),
          ('main', 'doc3.html#id-330'),
          ('', 'doc1.html#id-135'),
          ('', 'doc2.html#id-235'),
          ('', 'doc3.html#id-335')])],
       None])]),
   ('さ',
    [('さささ',
      [[],
       [('あああ かかか',
         [('main', 'doc1.html#id-136'),
          ('main', 'doc2.html#id-236'),
          ('main', 'doc3.html#id-336'),
          ('', 'doc1.html#id-131'),
          ('', 'doc2.html#id-231'),
          ('', 'doc3.html#id-331')])],
       None])]),
   ('す',
    [('すすす',
      [[],
       [('ううう くくく',
         [('main', 'doc1.html#id-138'),
          ('main', 'doc2.html#id-238'),
          ('main', 'doc3.html#id-333'),
          ('', 'doc1.html#id-133'),
          ('', 'doc2.html#id-233'),
          ('', 'doc3.html#id-338')])],
       None])]),
   ('分類',
    [('そそそ',
      [[],
       [('おおお こここ',
         [('main', 'doc1.html#id-130'),
          ('main', 'doc2.html#id-230'),
          ('main', 'doc3.html#id-330'),
          ('', 'doc1.html#id-135'),
          ('', 'doc2.html#id-235'),
          ('', 'doc3.html#id-335')])],
       '分類'])])]
]

class _domain(object):
    def __init__(self, entries):
        self.entries = entries

dmn = _domain(testcase1[0])

class _env(object):
    def __init__(self, domain):
        self.domain = {}
        self.domain['index'] = domain
    def get_domain(self, domain_type):
        return self.domain[domain_type]
env = _env(dmn)

#dummy
class _builder(object):
    def get_relative_uri(self, uri_type, file_name):
        return f'{file_name}.html'
bld = _builder()

class UnittextIndexEntries(unittest.TestCase):
    def test_create_index(self):
        self.maxDiff = None
        gidx = IndexEntries(env).create_index(bld)
        self.assertEqual(testcase1[1], gidx)

if __name__ == '__main__':
    unittest.main()
```

# 以上