-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Add testing helpers #3005
[WIP] Add testing helpers #3005
Conversation
f4ee69a
to
95cfbfe
Compare
self._cache = { | ||
'conditions': {} | ||
, 'order': None | ||
} | ||
|
||
def clearCache(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this new method as well as self.use_cache
do not seem related to the new testing helpers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I thought I'd need these when I started this, but since I throw away the check-runner instance after one time use, there's no actual need for a cache reset.
All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the ℹ️ Googlers: Go here for more info. |
@googlebot I consent. |
CLAs look good, thanks! ℹ️ Googlers: Go here for more info. |
|
The cff profile uses the conditions This is the cure: # in profiles/cff.py
profile_imports = [
('.shared_conditions', (is_cff', 'is_cff2'))
] |
If it takes the same input but produces different output, it should be a different check-id, because it is another function. It does not matter if the function was created by the override mechanism. |
Lib/fontbakery/codetesting.py
Outdated
# limitations under the License. | ||
# | ||
|
||
def get_check(profile, checkid): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this function is specific to FontsProfile
from fonts_profile.py
we should hint it in the name or put it somewhere else. e.g. could be called fonts_profile_get_check
and still be an import as get_check
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also make this behave roughly like pattern matching in Haskell, i.e. return a different implementation depending on the profile type (isinstance(profile, FontsProfile)
) ....
Lib/fontbakery/codetesting.py
Outdated
# elif isinstance(value[0], TTFont): | ||
# return execute_check_once(profile, checkid, "", | ||
# {'ttFonts': value}) | ||
return _checker |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd treat this like a decorator: https://docs.python.org/3.8/library/functools.html#functools.update_wrapper
from functools import update_wrapper
return update_wrapper(_checker, execute_check_once)
Lib/fontbakery/codetesting.py
Outdated
return execute_check_once(profile, checkid, value.reader.file.name, | ||
{'ttFont': value}) | ||
# | ||
# TODO: I am not sure how to properly handle these cases: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, I'll look into this. Especially because ttFonts
is a "derived_iterable" and that's not done with a cache override of conditions
.
|
thanks ;-) |
@felipesanches why a merge commit? Couldn't you |
I was actually checking with you on a different topic: I think the |
It was done automatically via github UI. I plan to squash and merge when we're good here |
@felipesanches seeing how you use this stuff, I think we may be better of implementing it differently. |
Here are some thoughts: When we simply run a check on a given sample font, the current implementation works well computing all the dependencies automatically. It also works well for the cases when we need to change values in tables of a TTF binary, because we naturally can have easy access to the fontTools TTFont object. One shortcoming though is that when we need to modify other things like a field in a METADATA.pb file (or contents of the DESCRIPTION.html file), then it is not trivial how to do it. It seems that it would be useful if the execution of a check could return a "context" object which we would be able to use to get access to the computed dependencies and eventually modify them before feeding this modified context to a second check execution (for the other test-cases in a given code test) |
I think such mechanism would be useful to improve code-tests like this one: https://github.com/googlefonts/fontbakery/blob/master/tests/profiles/googlefonts_test.py#L1420-L1456 |
@felipesanches I added a One thing it misses is that checks that would be skipped via conditions won't report that way, because the call to check is direct. However, I think the level of control, via the def test_check_metadata_nameid_full_name():
""" METADATA.pb font.fullname value matches fullname declared on the name table ? """
from fontbakery.codetesting import FontsTestingContext
check = FontsTestingContext(googlefonts_profile,
'com.google.fonts/check/metadata/nameid/full_name',
TEST_FILE("merriweather/Merriweather-Regular.ttf")
)
assert_PASS(check(), 'with a good font...')
# here we change the font.fullname on the METADATA.pb
# to introduce a "mismatch" error condition:
font_meta = check.args['font_metadata']
good = font_meta.full_name
font_meta.full_name = good + "bad-suffix"
assert_results_contain(check(),
FAIL, 'mismatch',
'with mismatching fullname values...')
# and restore the good value prior to the next test case:
font_meta.full_name = good
# And here we remove all FULL_FONT_NAME entries
# in order to get a "lacks-entry" error condition:
ttFont = check.args['ttFont']
for i, name in enumerate(ttFont["name"].names):
if name.nameID == NameID.FULL_FONT_NAME:
del ttFont["name"].names[i]
assert_results_contain(check(),
FAIL, 'lacks-entry',
'when a font lacks FULL_FONT_NAME entries in its name table...') Maybe we can use the TestingContext instead of the I think however, checking if |
thanks, @graphicore! I'll review it and suggest/implement changes later this week. At a quick glance, it looks promising, but I also see a few things I may want to change ;-) |
values = {'font': values.reader.file.name, | ||
'fonts': [values.reader.file.name], | ||
'ttFont': values, | ||
'ttFonts': [values]} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ttFonts
as values
won't have any effect.it's defined as a derrived_iterable
not as a value
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, font
is neither a value, it's an item from the iterable
of fonts
and ttfont
is not a value as well, it's a condition
of font
37160a6
to
1bbfa22
Compare
TEST_FILE and assert_... helpers are now on fontbakery.codetesting module
1bbfa22
to
cfe982e
Compare
cfe982e
to
06001ca
Compare
@graphicore, I have been refactoring more code-tests to use the new style. I also changed a bit more the implementation of the TestingContext class. I was not able to remove the I'll be doing all of the port of the remaining code-tests today and hopefully I think I can have it ready for merging very soon. |
I merged it now because other PRs are piling up and this one includes some linter fixes for those. I'll open another PR to resume work on this. |
Using the TestingContext helper class. (follow-up to PR fonttools#3005)
Using the TestingContext helper class. (follow-up to PR fonttools#3005)
Using the TestingContext helper class. (follow-up to PR fonttools#3005)
Using the TestingContext helper class. (follow-up to PR fonttools#3005)
Using the TestingContext helper class. (follow-up to PR #3005)
@felipesanches: I expect we'll have to iterate on this and possible further interfaces a bit. This is to get us started. Here's an example on how to use it: