From 1d1a8a95260f8b53e9b0db062ff0362a863054f7 Mon Sep 17 00:00:00 2001 From: sangamcse Date: Sat, 12 May 2018 21:18:17 +0530 Subject: [PATCH] cEP-0027.md: Add `Improve Lint Bear Quality` cEP This proposes the prototype of the feature of BaseTestHelper class and GlobalBearTestHelper class. BaseTestHelper class will be a normal base class, and it will grow from there later. GlobalBearTestHelper in coala testing API will add supports to the GlobalBear. Ref https://github.com/coala/coala/issues/3676 Ref https://github.com/coala/coala/issues/4884 --- cEP-0027.md | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 cEP-0027.md diff --git a/cEP-0027.md b/cEP-0027.md new file mode 100644 index 000000000..f740060c5 --- /dev/null +++ b/cEP-0027.md @@ -0,0 +1,144 @@ +# coala Bears Testing API + +| Metadata | | +| -------- | ----------------------------------------- | +| cEP | 27 | +| Version | 0.1 | +| Title | coala Bears Testing API | +| Authors | Sangam Kumar | +| Status | Proposed | +| Type | Feature | + +## Abstract + +This cEP describes the process of adding `BaseTestHelper` class and +`GlobalBearTestHelper` class to improve the testing API of coala bears, as a +part of the [GSoC 2018 project](https://summerofcode.withgoogle.com/projects/#6625036551585792). + +## Introduction + +[coala](https://coala.io) has its own testing API which includes +`LocalBearTestHelper`, a helper class for testing of local bears. It does not +provide support for `GlobalBear`. Writing tests for a `GlobalBear` is slightly +lengthy for a developer. Example: +[GitCommitBearTest](https://github.com/coala/coala-bears/blob/master/tests/vcs/git/GitCommitBearTest.py), +[VultureBearTest](https://github.com/coala/coala-bears/blob/master/tests/python/VultureBearTest.py), +etc. `GlobalBearTestHelper` is going to be a helper class for simplification of +testing of `GlobalBear`. + +Also, the testing API should have a base test helper class which should be +inherited in all tests' helper (LocalBearTestHelper, GlobalBearTestHelper). +This project introduces `BaseTestHelper` class, base class for all bear tests. + +## Proposed Approach + +### 1. Implementation of the `BaseTestHelper` class + +Issue: [coala/coala#3676](https://github.com/coala/coala/issues/3676) + +As mentioned in [introduction](#Introduction), `BaseTestHelper` class is the +base class for all bear tests. + +```py +class BaseTestHelper(object): + pass +``` + +Now, inherit the base test class in `LocalBearTestHelper` and +`GlobalBearTestBear`. E.g., + +```py +class LocalBearTestHelper(BaseTestHelper): + pass + +class GlobalBearTestHelper(BaseTestHelper): + pass +``` + +After implementation of `BaseTestHelper` class, it should be ensured that all +bear tests inherit from `BaseTestHelper` class using [pytest-restrict](https://pypi.org/project/pytest-restrict). +For example, in [`LocalBearTestHelperTest`](https://github.com/coala/coala/blob/master/tests/testing/LocalBearTestHelperTest.py), + +```py + out = self.runpytest('--restrict-types', + 'BaseTestHelper', + 'LocalBearTestHelper') + out.assert_outcomes(passed=2, failed=0) +``` + +### 2. Implementation of `GlobalBearTestHelper` class + +Issue: [coala/coala#4884](https://github.com/coala/coala/issues/4884) + +Currently, many methods are redundant in the tests of `GlobalBear`. For +example, all GlobalBears' tests have one method to collect absolute path of +test files and then those files are checked using the bear. + +```py + def get_absolute_test_path(file): + return "path/of/test_file/file" + + def get_results(self, files_to_check): + self.file_dict = [get_absolute_test_path(files_to_check)] + self.uut = AnyGlobalBear(self.file_dict, self.section, self.queue) + return list(self.uut.run()) + + def test_results(self): + results = self.get_results([self.test_files1, self.test_files2]) + messages = [result.message for result in results] + assert messages == ["This is message 1.", + "This is message 2."] +``` + +Instead of writing these methods each time during tests of `GlobalBear`, it +should be written once in `GlobalBearTestHelper` class with less flaws and +better design which will be easy to reuse and less effort will be required to +maintain. + +Here is the prototype implementation of these repeating methods into +`GlobalBearTestHelper` using [pytest](https://pytest.org/), and +[GlobalBear](http://api.coala.io/en/latest/coalib.bears.html#module-coalib.bears.GlobalBear): + +```py +def get_test_path(test_dir, file): + return os.path.join(os.path.dirname(__file__), test_dir, file) + +def get_results(global_bear, test_dir, file_dict, settings={}): + for file in file_dict: + with get_test_path(test_dir, file) as fname, + execute_bear(global_bear, fname, **settings) as bear_output: + return bear_output + +@contextmanager +def execute_bear(bear, *args, **kwargs): + try: + bear_output_generator = bear.execute(*args, **kwargs) + assert bear_output_generator is not None, \ + 'Bear returned None on execution\n' + yield bear_output_generator + except Exception as err: + msg = [] + while not bear.message_queue.empty(): + msg.append(bear.message_queue.get().message) + raise AssertionError(str(err) + ' \n' + '\n'.join(msg)) + return list(bear_output_generator) + + +class GlobalBearTestHelper(BaseTestHelper): + def check_results(self, global_bear, test_dir, file_dict, results, settings={}): + if results in [[], ()]: + msg = ("The global bear '{}' yields a result although " + "it shouldn't.".format(global_bear.__class__.__name__)) + + else: + msg = ("The global bear '{}' doesn't yield the right " + "results.".format(global_bear.__class__.__name__)) + + bear_output = get_results(global_bear, + test_dir=test_dir, + file_dict=file_dict, + settings=settings) + + assert bear_output == results, msg=msg + return bear_output +```