(1) could we consider explicitly just sort of usin...
# development
a
(1) could we consider explicitly just sort of using your four-word descriptions as the snake-cased method names directly? (2) it sounds like your #3 and #4 are reasonable to keep separate for now! (3)
integration tests for Pants
this isn't 100% clear imho. perhaps "integration test for pants plugin code"?
h
could we consider explicitly just sort of using your four-word descriptions as the snake-cased method names directly
Possibly. Related is that we need to answer where the utils live, also, e.g. *
testutil/rule_unit_tests.py
*
testutil/rule_integration_test.py
But then I didn’t like this at all:
Copy code
from pants.testutil.rule_integration_test import RuleRunner
It’s not predictable. I’m pretty sure that we want to call this type
RuleRunner
. Which led to me thinking we have
Copy code
from pants.testutil.rule_runner import RuleRunner

def test() -> None:
  RuleRunner.run_rule_with_mocks(foo, gets=MockGet(...))

// or

def test(rule_runner: RuleRunner) -> None:
   rule_runner.request_product(P, [S])
a
ok i think that setup makes sense as more describing what it is rather than what it does, thanks
i personally prefer the explicit injection of
RuleRunner
h
i personally prefer the explicit injection of RuleRunner
This is the part I don’t love about my proposal. With
run_rule
/ aka
RuleRunner.run_rule_with_mocks()
, you do not want to have to actually create an instance of
RuleRunner
. That’s more setup than you’d like, and
run_rule()
will ignore all that setup. It’s a classmethod for that reason, so you would not have it injected via a fixture But that’s really subtle, and I could see plugin authors unintentionally doing more work than they really need to
Which leads me to think that
run_rule()
should probably be a separate file from
TestBase
/ aka
RuleRunner
. But
run_rule()
now needs a new name
a
ok yes re: classmethod making it not directly useful to "inject" anything
👍 1
i think the word "runner" sounds more integration-testy to me, so i would consider like
execute_rule()
or
simulate_rule()
perhaps?
h
Great point about the connotation of run. I like
simulate_rule()
, I think! The tricky thing is it does actually execute your rule, just not any of the things outside your rule like `Get`s and the inputs to your rule
⁉️ 1
which is where I was thinking
run_rule_with_mocks()
. Maybe
execute_rule_with_mocks()
? Does that still live in
engine_util.py
?
Copy code
testutil/
  engine_util.py
  rule_runner.py
  pants_integration_test.py
  option_util.py
a
ok yes! i like that
i think you could break out a new file for the
run_rule_with_mocks()
method. i think your 1/2/3/4 classification makes sense
h
I suspect that
engine_util.execute_rule_with_mocks()
would be the least used of the 4 approaches, as that’s not super discoverable. But also honestly maybe not a huge deal. I suspect after writing these plugin docs that the vast majority of plugin authors will want approaches #3 and #4 In our own repo,
run_rule()
is really only useful for our highly generic rules like
test.py
and
lint.py
🔥 1
a
In our own repo, run_rule() is really only useful for our highly generic rules like test.py and lint.py
that's a great point and should maybe be included in docs if not already??
h
Agreed 🙂 not yet in the docs as I’ve been waiting to figure out what approaches #2 and #3 will look like.
pants_run()
is the first that’s seen lots of love, and today’s changes were for
TestBase
I’m glad you like the prototype for
RuleRunner
! I’m going on a 4 day roadtrip (flying for the first part to get the car), and might finish the prototype on the flight tomorrow
Okay, I think
run_rule_with_mocks()
as a top-level function in
rule_runner.py
. So you could have this:
Copy code
from pants.testutil.rule_runner import RuleRunner, run_rule_with_mocks

@pytest.fixture
def rule_runner() -> RuleRunner:
    return RuleRunner(rules=[...])

def test_foo() -> None:
      result = run_rule_with_mocks(my_rule, inputs=[...], mock_gets=[...])

def test_bar(rule_runner: RuleRunner) -> None:
    result = rule_runner.request_product(P, [s1, s2])