Skip to content

[3.0][Testing] Add unit tests for SMF\Lang and TimeInterval::localize() - #9582

Merged
Sesquipedalian merged 3 commits into
SimpleMachines:release-3.0from
albertlast:tests/lang-no-db
Aug 29, 2026
Merged

[3.0][Testing] Add unit tests for SMF\Lang and TimeInterval::localize()#9582
Sesquipedalian merged 3 commits into
SimpleMachines:release-3.0from
albertlast:tests/lang-no-db

Conversation

@albertlast

@albertlast albertlast commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Description

#9581 removes SMF\Lang's dependency on the database. This is the coverage that
unlocks, on top of it.

Until that change, none of the file-reading half of SMF\Lang was reachable from a
test. Asking for a language string went load() -> addDirs() ->
Theme::loadEssential(), and the Theme constructor's first act is a query, so a
process with no connection died on Typed static property SMF\Db\DatabaseApi::$db must not be accessed before initialization thrown out of Theme.php - a message with
nothing about languages in it, three calls below where the test was looking.

tests/Unit/LangTest.php

Seven tests, 15 assertions: loading a file, defaulting to the forum language when
there is no user, the directories addDirs() settles on when there is no theme to
ask, a custom directory that is not there being ignored, listing the installed
languages, loading a file because a string was asked for from it, and finding a
string that exists only on disk.

Worth being precise about what is new, because it is narrower than it looks:
censorText(), sentenceList(), numberFormat(), formatText(),
tokenTxtReplace() and getLocaleFromLanguageName() never needed the database and
could always have been tested. What was blocked is everything that has to find a file
first.

Lang::$dirs is read through reflection in two of these. It is private and has no
accessor, but which directories end up in it is the whole behaviour under test, and
every other assertion can only see that a file was found somewhere.

tests/Unit/TimeIntervalTest.php

That file carried a note saying localize() belonged to an integration suite,
because every branch of it goes through Lang::getTxt(). That is no longer true, so
the note goes and the five tests it stood in for arrive, 7 assertions between them:
each unit pluralised on its own value into a sentence, the unit order not depending
on how the caller wrote the argument, and asking for the total number of days falling
back to years, months and days when the interval has no total rather than producing a
flat "0 days" - the half of #9499 that toParsable() could only imply with the
strings hard coded. Plus the two edges around an empty result.

The thirteen tests already in the file are untouched.

Why the unit suite rather than the integration one

#9347 extends the test system to cover what genuinely needs a database, and that is
where anything reaching Db::$db belongs. But Lang is mostly string handling and
file loading, and a test that needs no database is far cheaper: this suite finishes
in under a second, runs on every pull request on 8.4 and 8.5, and needs no Docker and
no installed forum behind it. So these belong here, and #9581 is what lets them be
here. The two suites are complements.

Verified
  • 12 new tests and 22 new assertions: 7 tests / 15 assertions in the new
    LangTest, and 5 tests / 7 assertions added to TimeIntervalTest. That takes the
    suite from 139 tests and 205 assertions to 151 tests and 227 assertions.
  • Green - and green with --order-by=random, which is the check that matters here,
    since PHPUnit does not reset SMF's statics between tests and each of these leaves a
    loaded language behind. tearDown() puts Lang back to nothing loaded.
  • All twelve of the new ones fail against release-3.0 with the database error
    above, and pass on top of [3.0] Removes SMF\Lang's dependency on the database #9581. The 139 that were already there pass either way.
  • php-cs-fixer clean on both files; check-signed-off.php, check-smf-index.php,
    check-smf-license.php and check-eof.php all exit 0.

Merge order

Merge #9581 before this one. This branch contains it, so the diff shown here is
its commit as well as the two test commits; once it lands and this is rebased on
release-3.0, what is left is tests/Unit/LangTest.php and the localize() tests.

Issues References (Fixes|Related|Closes)

  1. Depends on [3.0] Removes SMF\Lang's dependency on the database #9581 - these tests fail without it.
  2. Related to [3.0] Restores full compatibility of SMF\TimeInterval with \DateInterval #9499 - the localize() behaviour it changed is what the new
    TimeIntervalTest cases pin.
  3. Related to [3.0][Testing] Add HTTP smoke tests that drive a running forum #9347 - the other side of the same split, for code that does need a
    database.

Sesquipedalian and others added 3 commits August 29, 2026 13:46
Previously, trying to load any language strings required the theme to be loaded, which in turn required the database to be loaded. Now we simply skip the theme stuff if the database is not available.

Signed-off-by: Jon Stovell <jonstovell@gmail.com>
Until the change this builds on, none of it was reachable from a test. Asking
for a language string went load() -> addDirs() -> Theme::loadEssential(), and
the Theme constructor's first act is a query, so a process with no connection
died on "Typed static property SMF\Db\DatabaseApi::$db must not be accessed
before initialization" thrown out of Theme.php - a message with nothing about
languages in it, three calls below where the test was looking.

Seven tests, all of which fail with that error against release-3.0 and pass on
top of the parent commit: loading a file, defaulting to the forum language when
there is no user, the directories addDirs() settles on when there is no theme
to ask, a custom directory that is not there being ignored, listing the
installed languages, loading a file because a string was asked for from it, and
finding a string that exists only on disk.

Worth being precise about what is new: censorText(), sentenceList(),
numberFormat(), formatText(), tokenTxtReplace() and getLocaleFromLanguageName()
never needed the database and could always have been tested. What was blocked
is everything that has to find a file first.

Lang::$dirs is read through reflection in two of these. It is private and has
no accessor, but which directories end up in it is the whole behaviour under
test, and every other assertion here can only see that a file was found
somewhere.

PHPUnit does not reset SMF's statics between tests, and each of these leaves a
loaded language behind, so tearDown() puts Lang back to nothing loaded. The
suite is green in random order as well as in file order.

Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
This file carried a note saying localize() belonged to an integration suite:
every branch of it goes through Lang::getTxt(), which loads a language file,
which wanted Theme::$current and therefore Db::$db. That is no longer true on
top of the parent commit, so the note goes and the tests it stood in for
arrive.

They cover the other half of what SimpleMachines#9499 put right, which toParsable() above
could only imply with the strings hard coded: each unit pluralised on its own
value into a sentence, the unit order not depending on how the caller wrote the
argument, and asking for the total number of days falling back to years, months
and days when the interval has no total rather than producing a flat "0 days".
Plus the two edges around an empty result - saying zero of the smallest unit
asked for, and folding fractional seconds into the seconds.

All five fail against release-3.0 with the database error the note described,
and pass here. The thirteen tests already in the file are untouched.

tearDown() puts Lang's statics back, for the same reason the Lang tests do.

Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
@github-actions github-actions Bot added Localization Language & internationalization Unit Testing labels Aug 29, 2026
@jdarwood007 jdarwood007 added this to the 3.0 Alpha 6 milestone Aug 29, 2026
@Sesquipedalian
Sesquipedalian merged commit 688d82d into SimpleMachines:release-3.0 Aug 29, 2026
7 checks passed
@jdarwood007 jdarwood007 modified the milestones: 3.0 Alpha 6, 3.0 Alpha 5 Aug 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Localization Language & internationalization Unit Testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants