Skip to content

Add support for unit test style tests (non-analysis tests) #37

@rickeylev

Description

@rickeylev

The analysis_test wrapper requires a target-under-test to be specified, but this is unnecessary when a non-analysis test is being written, e.g. one that verifies utility code.

The goal is to simply unittest style tests much like was done for analysis tests, for reference, a a typical unit test looks like this:

def impl(ctx):
  env = unittest.begin(ctx)
  expect = truth.expect(env)
  expect.that_str(helper()).equals("expected")
  return unittest.end(env)

foo_test = unittest.make(impl)

def create_test_suite(name):
  foo_test(name + "foo_test")
  test_suite(name = name, tests = ["foo_test"])

The unappealing parts of this are:

  • Manually managing the env create/return
  • foo_test has to be bound, instantiated, and passed by name. Seems like a lot of boilerplate.
  • To use truth, this also means having to manually instantiate truth. Not a huge deal, but more boilerplate.

I'm not sure how this could be best cleaned up. A directly translation to analysis test is a bit verbose, because the "setup" part of an analysis test doesn't seem necessary for a unit test.

Maybe something like this, ideally:

suite = []
def _foo_test(env):
  env.expect.that_str(helper()).equals("expected")

suite.append(_foo_test)

def create_test_suite(name):
  test_suite(name=name, unit_tests=suite)

# in rules_testing
def test_suite(name, unit_tests):
  for unit_test_impl in unit_tests:
    test_name = name_from_func(unit_test_impl)
    testing.unit_test(name = name + test_name, impl=unit_test_impl)

There's no testing.unit_test currently; perhaps there should be. I think we can approximate this using testing.analysis_test by just passing a stub target as the thing under test and using a couple wrapper functions.

It'd also be nice if a single test_suite() invocation could Just Work with a mixture of analysis tests and unit tests. The above idea doesn't quite allow that. Maybe if an adapter function converted the impl function to something matching analysis_test's expectations, e.g.

def adapt(impl):
  def setup(name):
    testing.unittest(name=name, impl=impl)
  return setup

suite.append(adapt(impl))

This seems appealing because it allows a unit test to utilizing the load phase to do stuff. I don't know what stuff would be, though. Maybe some more advanced case where the impl is a lambda of some sort, or additional args need to be passed onto the testing.unittest call (tags, platform constraints, etc)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions