Add Objective-C alternative token tests
This commit is contained in:
Родитель
68d805f73a
Коммит
542f18fd16
11
README.md
11
README.md
|
@ -88,6 +88,8 @@ blacklist = ["test_identifier_1", "test_identifier_2"]
|
|||
|
||||
Most tests have configurable rules. If a rule is not specified, it will use the default instead.
|
||||
|
||||
Some tests are opt in only. These will be marked as such.
|
||||
|
||||
## Comment Similarity
|
||||
|
||||
Identifier: `comment_similarity`
|
||||
|
@ -153,6 +155,15 @@ _Note: By default this test doesn't check anything. It needs to have parameters
|
|||
|
||||
</details>
|
||||
|
||||
## Objective-C Alternative Tokens
|
||||
|
||||
Identifier: `objectivec_alternative_tokens`
|
||||
Opt-In: `true`
|
||||
|
||||
Checks that strings do not contain Objective-C style alternative position tokens.
|
||||
|
||||
Objective-C seems to be allows positional tokens of the form `%1@` rather than `%1$@`. While not illegal, it is preferred that all tokens between languages are consistent so that tools don't experience unexpected failures, etc.
|
||||
|
||||
## Token Matching
|
||||
|
||||
Identifier: `token_matching`
|
||||
|
|
|
@ -54,12 +54,17 @@ def run_tests(configuration: Configuration, collection: LocalizedCollection) ->
|
|||
|
||||
test_classes = _find_tests()
|
||||
blacklist = set(configuration.blacklist())
|
||||
opt_ins = set(configuration.opt_in())
|
||||
|
||||
results = []
|
||||
|
||||
for test_class in test_classes:
|
||||
if test_class.name() in blacklist:
|
||||
continue
|
||||
|
||||
if test_class.is_opt_in() and test_class.name() not in opt_ins:
|
||||
continue
|
||||
|
||||
test_instance = test_class(configuration, collection)
|
||||
results.append(test_instance.execute())
|
||||
|
||||
|
|
|
@ -29,6 +29,13 @@ class Configuration:
|
|||
"""
|
||||
return self.raw_config.get("blacklist", [])
|
||||
|
||||
def opt_in(self) -> List[str]:
|
||||
"""Return the list of opted in tests.
|
||||
|
||||
:returns: The opted in tests
|
||||
"""
|
||||
return self.raw_config.get("opt_in", [])
|
||||
|
||||
def get_test_preferences(self, name: str) -> Dict[str, Any]:
|
||||
"""Get the preferences for a given test.
|
||||
|
||||
|
|
|
@ -5,5 +5,6 @@ import localizationkit.tests.has_comments
|
|||
import localizationkit.tests.has_value
|
||||
import localizationkit.tests.invalid_tokens
|
||||
import localizationkit.tests.key_length
|
||||
import localizationkit.tests.objectivec_alternative_tokens
|
||||
import localizationkit.tests.token_matching
|
||||
import localizationkit.tests.token_position_identifiers
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
"""Objective-C alternative tokens."""
|
||||
|
||||
import re
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from localizationkit.tests.test_case import LocalizationTestCase
|
||||
|
||||
|
||||
class ObjectivecAlternativeTokens(LocalizationTestCase):
|
||||
"""Check for Objective-C alternative tokens.
|
||||
|
||||
Objective-C seems to be perfectly happy with positional tokens of the form
|
||||
%1@ rather than %1$@. While not illegal, it is preferred that they are
|
||||
consistent so that tools don't experience unexpected failures, etc.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def name(cls) -> str:
|
||||
return "objectivec_alternative_tokens"
|
||||
|
||||
@classmethod
|
||||
def default_settings(cls) -> Dict[str, Any]:
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def is_opt_in(cls) -> bool:
|
||||
return True
|
||||
|
||||
def run_test(self) -> List[str]:
|
||||
|
||||
violations = []
|
||||
|
||||
pattern = re.compile(r"(%(?:[0-9]+)(?:\.[0-9]+)?[@a-z][a-z]?)", flags=re.DOTALL)
|
||||
|
||||
for string in self.collection.localized_strings:
|
||||
|
||||
if pattern.findall(string.value):
|
||||
violations.append(f"Objective-C altnernative tokens were found in string: {string}")
|
||||
continue
|
||||
|
||||
return violations
|
|
@ -52,6 +52,17 @@ class LocalizationTestCase(abc.ABC):
|
|||
"""
|
||||
raise NotImplementedError("default_settings should always be overridden")
|
||||
|
||||
@classmethod
|
||||
def is_opt_in(cls) -> bool:
|
||||
"""Check if the test is opt in or not.
|
||||
|
||||
Not all tests make sense for everyone (e.g. language specific tests), so
|
||||
we make those opt in
|
||||
|
||||
:returns: True if this is an opt in method, False otherwise
|
||||
"""
|
||||
return False
|
||||
|
||||
@abc.abstractmethod
|
||||
def run_test(self) -> List[str]:
|
||||
"""Run the test
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
"""Objective-C alternative token tests."""
|
||||
|
||||
# pylint: disable=line-too-long
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "..")))
|
||||
import localizationkit
|
||||
|
||||
|
||||
class ObjectivecAlternativeTokenTests(unittest.TestCase):
|
||||
"""Objective-C alternative token tests."""
|
||||
|
||||
def setUp(self):
|
||||
current_file_path = os.path.abspath(__file__)
|
||||
current_folder_path = os.path.dirname(current_file_path)
|
||||
self.config_path = os.path.abspath(os.path.join(current_folder_path, "config.toml"))
|
||||
self.configuration = localizationkit.Configuration.from_file(self.config_path)
|
||||
|
||||
def test_alternative_tokens(self):
|
||||
"""Test that the Objective-C alternative token test works"""
|
||||
|
||||
good_values = ["%@", "%1$@", "%%", "%%1"]
|
||||
|
||||
bad_values = ["%1@", "%1@ %2@"]
|
||||
|
||||
for value in good_values:
|
||||
string = localizationkit.LocalizedString("Key", value, "Comment", "en")
|
||||
collection = localizationkit.LocalizedCollection([string])
|
||||
test = localizationkit.tests.objectivec_alternative_tokens.ObjectivecAlternativeTokens(
|
||||
self.configuration, collection
|
||||
)
|
||||
result = test.execute()
|
||||
self.assertTrue(result.succeeded(), str(result.violations))
|
||||
|
||||
for value in bad_values:
|
||||
string = localizationkit.LocalizedString("Key", value, "Comment", "en")
|
||||
collection = localizationkit.LocalizedCollection([string])
|
||||
test = localizationkit.tests.objectivec_alternative_tokens.ObjectivecAlternativeTokens(
|
||||
self.configuration, collection
|
||||
)
|
||||
result = test.execute()
|
||||
self.assertFalse(result.succeeded())
|
Загрузка…
Ссылка в новой задаче