Skip to content

Test fetch v2 #22367

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

Merged
merged 28 commits into from
Mar 31, 2023
Merged

Test fetch v2 #22367

merged 28 commits into from
Mar 31, 2023

Conversation

sgugger
Copy link
Collaborator

@sgugger sgugger commented Mar 24, 2023

What does this PR do?

This PR rewrites the test fetcher util to be more accurate in the tests collection, and also comes with a restriction on the tests run when a large amount of tests are picked when modifying a core file (like modeling_utils).

The code that extracts the dependencies of a given module now inspects the inits to pinpoint the exact location of imported objects. So for instance if a test file has an import from transformers import BertModel, this new version will detect a dependency on transformers/models/bert/modeling_bert.py. As a comparison, the previous version stopped at transformers/__init__.py. This removes the need for all the complex logic that tried to match a given file with its corresponding tests, we now just look at the dependencies of the test file.

The second change is that when a given file is seen to trigger too many model tests (current trigger is set at half the models, it can evolve), it will only keep the tests relative to a given list of important models. If a PR changes many modeling files, all the tests for those models will still run, but if a PR only changes modeling_utils (for instance), this will trigger the core model tests only. The list of important models is built using:

  • the most downloaded models in the last 30 days
  • making sure each pipeline has a model in that list

To bypass this rule, one can add a special command in a commit message (circleCI does not have access to labels, so I can't rely on that):

  • Including [skip ci] or [ci skip] or [circleci skip] or [skip circleci] or any variants with - or _ instead of a space will skip all tests
  • Including [test all models] or any variant with the words in another order and/or with - or _ instead of a space will run all tests found without filtering on important models.
  • Including [test all] or [all test] or any variants with - or _ instead of a space will run all tests.

A couple of adjustments to Transformers should be done (in follow-up PRs) to have the test fetcher be more accurate and more efficient:

  • make sure all inits don't define any objects. Most of our inits only import all the stuff, and the test fetcher assumes they are all like that. Some inits (like pipeline/__init__.py) define real objects, it would be best to move them to a submodule.
  • make sure test files test one thing: for instance test_modeling_common.py contains both the common tests and the test of the modeling_utils module. It would be best to split those in two files.

Lastly, this PR adds lots of tests to make sure future work doesn't break the test fetcher :-)

To see how the test fetcher behaves on some examples:

  • for a modification in modeling_opt.py: only test_modeling_opt is run [fetch summary] [job page]
  • for a modification in modeling_bert.py (which is imported in all the tests basically) all tests using BERT are run, but filtered to the list of important models [fetch summary] [job page]
  • for a modification in a pipeline file: all model tests are run, filtered to the list of important models [fetch summary] [job page]
  • for a modification in the main __init__.py all tests are run, but filtered to the list of important models [fetch summary] [job page]
  • for a modification in the setup.py all tests are run [fetch summary] [job page]

@HuggingFaceDocBuilderDev
Copy link

HuggingFaceDocBuilderDev commented Mar 24, 2023

The documentation is not available anymore as the PR was closed or merged.

@ydshieh ydshieh self-assigned this Mar 27, 2023
@ydshieh
Copy link
Collaborator

ydshieh commented Mar 29, 2023

I guess it's ready for a review?

@sgugger
Copy link
Collaborator Author

sgugger commented Mar 29, 2023

No I haven't finished this PR yet.

Copy link
Member

@LysandreJik LysandreJik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, LGTM! Looking forward to seeing it run!

@@ -667,11 +611,29 @@ def filter_tests(output_file, filters):
f.write(" ".join(test_files))


def parse_commit_message(commit_message):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would tend to favor explicit returns such as a dict {"skip": skip, "all_models": all_models, "test_all": test_all} so that we don't need to look for the docs to understand what to do with the returned value

Comment on lines +138 to +140
# Sagemaker tests are not meant to be run on the CI.
if "tests/sagemaker" in tests:
tests.remove("tests/sagemaker")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to verify with @philschmid

@ydshieh
Copy link
Collaborator

ydshieh commented Mar 31, 2023

Hi @sgugger . Thank you a lot for working on this important task! I feel it's better for me to look this work in depth, and I tried to play with the test fetcher (on main and on this PR) to understand it better.

However, the first thing I tried (by following some sentences you mentioned) makes me a somehow confused. Here is what I saw:

  • On the two branches main (or a new branch from it) and test_fetch_v2, do the following steps:

    • change the test file tests/models/bert/test_modeling_bert.py (simply adding some dummy line like foo = 1)
    • commit the change
      git add tests/models/bert/test_modeling_bert.py
      git commit -m "dummy commit"
    • run the test fetcher against the previous commit
      python utils/tests_fetcher.py  --diff_with_last_commit
  • Now, the results:
    TL;DR: test_modeling_bert.py is not included by the new version of test fetcher. But I think it should be included.

    • on main
      (tests/models/bert/test_modeling_bert.py is in TEST TO RUN and in the file test_list.txt)

      ### DIFF ###
      
      ### MODIFIED FILES ###
      - tests/models/bert/test_modeling_bert.py
      
      ### IMPACTED FILES ###
      - tests/models/auto/test_modeling_auto.py
      - tests/models/auto/test_modeling_tf_auto.py
      - tests/models/bert/test_modeling_bert.py
      - tests/models/encoder_decoder/test_modeling_encoder_decoder.py
      - tests/models/speech_encoder_decoder/test_modeling_speech_encoder_decoder.py
      - tests/models/vision_encoder_decoder/test_modeling_vision_encoder_decoder.py
      - tests/models/vision_text_dual_encoder/test_modeling_vision_text_dual_encoder.py
      
      ### TEST TO RUN ###
      - tests/models/auto/test_modeling_auto.py
      - tests/models/auto/test_modeling_tf_auto.py
      - tests/models/bert/test_modeling_bert.py
      - tests/models/encoder_decoder/test_modeling_encoder_decoder.py
      - tests/models/speech_encoder_decoder/test_modeling_speech_encoder_decoder.py
      - tests/models/vision_encoder_decoder/test_modeling_vision_encoder_decoder.py
      - tests/models/vision_text_dual_encoder/test_modeling_vision_text_dual_encoder.py
      
    • on test_fetch_v2
      (tests/models/bert/test_modeling_bert.py is NEITHER in TEST TO RUN, NOR in the file test_list.txt)

      ### MODIFIED FILES ###
      - tests/models/bert/test_modeling_bert.py
      
      ### IMPACTED FILES ###
      - tests/models/auto/test_modeling_auto.py
      - tests/models/auto/test_modeling_tf_auto.py
      - tests/models/bert/test_modeling_bert.py
      - tests/models/encoder_decoder/test_modeling_encoder_decoder.py
      - tests/models/speech_encoder_decoder/test_modeling_speech_encoder_decoder.py
      - tests/models/vision_encoder_decoder/test_modeling_vision_encoder_decoder.py
      - tests/models/vision_text_dual_encoder/test_modeling_vision_text_dual_encoder.py
      
      ### TEST TO RUN ###
      - tests/models/auto/test_modeling_auto.py
      - tests/models/auto/test_modeling_tf_auto.py
      - tests/models/encoder_decoder/test_modeling_encoder_decoder.py
      - tests/models/speech_encoder_decoder/test_modeling_speech_encoder_decoder.py
      - tests/models/vision_encoder_decoder/test_modeling_vision_encoder_decoder.py
      - tests/models/vision_text_dual_encoder/test_modeling_vision_text_dual_encoder.py
      

@ydshieh
Copy link
Collaborator

ydshieh commented Mar 31, 2023

As a comparison, the previous version stopped at transformers/init.py.

Is the following block (on main) what you mentioned by the above sentence?

    # We ignore the main init import as it's only for the __version__ that it's done
    # and it would add everything as a dependency.
    if not imported_module.endswith("transformers/__init__.py"):
        ...

[Not question - just to record something so I won't forget later]
I tried to change src/transformers/models/bert/modeling_bert.py, and I can see

  • src/transformers/__init__.py is given as impacted in both versions
  • src/transformers/models/gpt2/xxx is given as impacted in the version on main but not the version on this PR
  • tests/models/gpt2/xxx is NOT given as impacted in the version on main but given in the version on this PR.
    • but its in tests to run in bother version

@ydshieh
Copy link
Collaborator

ydshieh commented Mar 31, 2023

Well, at least, when src/transformers/models/bert/modeling_bert.py is changed, the test file tests/models/bert/test_modeling_bert.py included 👍 . So the dependency detection seems to work well, and the above situation is just an edge case (to including self)

Copy link
Collaborator

@amyeroberts amyeroberts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No comments other than to say this was a very interesting and enjoyable PR to review ❤️

Thanks for adding!


# List here the models to always test.
IMPORTANT_MODELS = [
# Most downloaded models
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we have a reminder somewhere to periodically update this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure people are going to go read this periodically ;-) It's more of us to think of it when we add a new pipeline for instance.

return get_diff(repo, repo.head.commit, parent_commits)


# (:?^|\n) -> Non-catching group for the beginning of the doc or a new line.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Detailed comments explaining regex ❤️ ❤️ ❤️

def test_infer_tests_to_run(self):
with tempfile.TemporaryDirectory() as tmp_folder:
tmp_folder = Path(tmp_folder)
models = models = ["bert", "gpt2"] + [f"bert{i}" for i in range(10)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for reassigning models here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a typo ;-)

@sgugger
Copy link
Collaborator Author

sgugger commented Mar 31, 2023

@ydshieh, good catch on a modified test file missing from the tests launched. I have only put the dependencies and forgot those. Will fix.

@sgugger
Copy link
Collaborator Author

sgugger commented Mar 31, 2023

@ydshieh did you want to review more or is it good to merge?

@ydshieh
Copy link
Collaborator

ydshieh commented Mar 31, 2023

@ydshieh did you want to review more or is it good to merge?

Hi @sgugger If you feel urgent to merge, go ahead (I can leave comments afterward anyway). Otherwise, I would love to continue the review process despite I am slow.

Copy link
Collaborator

@ydshieh ydshieh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @sgugger again for the great work and the patience for my slow review.

I am actually learning things here rather than giving useful reviews, but left 2 nits (typo and var. naming).

"""
with open(os.path.join(PATH_TO_TRANFORMERS, module_fname), "r", encoding="utf-8") as f:
if cache is not None and module_fname in cache:
return cache[module_fname]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice! I actually missed these 2 lines during the review, and I was thinking why not using cache but just adding content at the end.

f for f in modified_files if f.startswith("tests") and f.split(os.path.sep)[-1].startswith("test")
]
# Then we grab the corresponding test files.
test_map = create_module_to_test_map(reverse_map=reverse_map, filter_models=filter_models)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good not to create reverse_map twice!

Comment on lines 690 to 693
if commit_flags["test_all_models"]:
print("Testing all models found.")
if commit_flags["test_all"]:
print("Force- launching all tests")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When reading this part, I feel confused between between "test_all_models" and "test_all".
Maybe run_fetched_tests and run_all_tests make it more clear.
Leave you to decide.

(and "Run all fetched tests.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going for no_filter instead, as I find it clearer and shorter than run_fetched_tests.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😮 💯 🔥

@sgugger sgugger merged commit c612628 into main Mar 31, 2023
@sgugger sgugger deleted the test_fetch_v2 branch March 31, 2023 20:18
@HuggingFaceDocBuilderDev

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint.

raghavanone pushed a commit to raghavanone/transformers that referenced this pull request Apr 5, 2023
* Test fetcher v2

* Fix regexes

* Remove sanity check

* Fake modification to OPT

* Fixes some .sep issues

* Remove fake OPT change

* Fake modif for BERT

* Fake modif for init

* Exclude SageMaker tests

* Fix test and remove fake modif

* Fake setup modif

* Fake pipeline modif

* Remove all fake modifs

* Adds options to skip/force tests

* [test-all-models] Fake modif for BERT

* Try this way

* Does the command actually work?

* [test-all-models] Try again!

* [skip circleci] Remove fake modif

* Remove debug statements

* Add the list of important models

* Quality

* Update utils/tests_fetcher.py

Co-authored-by: Lysandre Debut <[email protected]>

* Address review comments

* Address review comments

* Fix and add test

* Apply suggestions from code review

Co-authored-by: Yih-Dar <[email protected]>

* Address review comments

---------

Co-authored-by: Lysandre Debut <[email protected]>
Co-authored-by: Yih-Dar <[email protected]>
novice03 pushed a commit to novice03/transformers that referenced this pull request Jun 23, 2023
* Test fetcher v2

* Fix regexes

* Remove sanity check

* Fake modification to OPT

* Fixes some .sep issues

* Remove fake OPT change

* Fake modif for BERT

* Fake modif for init

* Exclude SageMaker tests

* Fix test and remove fake modif

* Fake setup modif

* Fake pipeline modif

* Remove all fake modifs

* Adds options to skip/force tests

* [test-all-models] Fake modif for BERT

* Try this way

* Does the command actually work?

* [test-all-models] Try again!

* [skip circleci] Remove fake modif

* Remove debug statements

* Add the list of important models

* Quality

* Update utils/tests_fetcher.py

Co-authored-by: Lysandre Debut <[email protected]>

* Address review comments

* Address review comments

* Fix and add test

* Apply suggestions from code review

Co-authored-by: Yih-Dar <[email protected]>

* Address review comments

---------

Co-authored-by: Lysandre Debut <[email protected]>
Co-authored-by: Yih-Dar <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants