Skip to content
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

testing section for tripal importer #113

Open
bradfordcondon opened this issue Sep 17, 2018 · 0 comments
Open

testing section for tripal importer #113

bradfordcondon opened this issue Sep 17, 2018 · 0 comments

Comments

@bradfordcondon
Copy link
Member

the testing part of the tripalimporter section was suggested to be moved to this repo instead.

The full testing portion is below...


Testing Importers
------------------
Unit Testing is a critically important component of any software project. You should always strive to write tests for your software.  Tripal provides unit testing using the ``phpunit`` testing framework. The Tripal Test Suite provides a strategy for adding tests for your new Importer.  It will automatically set up and bootstrap Drupal and Tripal for your testing environment, as well as provide database transactions for your tests, and factories to quickly generate data.  We will use the Tripal Test Suite to provide unit testing for our ``ExampelImporter``.

.. note::
  Before continuing, please install and configure Tripal Test Suite.

  For instructions on how to install, configure, and run Tripal Test Suite, `please see the Tripal Test Suite documentation. <https://tripaltestsuite.readthedocs.io/en/latest/>`_


Example file
^^^^^^^^^^^^
When developing tests, consider including a small example file as this is good practice both to ensure that your loader works as intended, and for new developers to easily see the expected file format.  For our ``ExampleImporter``, we'll include the following sample file and store it in this directory of our module:  ``tests/data/example.txt``.

.. csv-table:: Example input file
  :header: "Feature name", "CVterm value"

  "test_gene_1", "blue"
  "test_gene_2", "red"


Loading the Importer
^^^^^^^^^^^^^^^^^^^^
Testing your loader requires a few setup steps.  First, TripalImporters are not explicitly loaded in your module (note that we never use ``include_once()`` or ``require_once`` in the ``.module`` file).  Normally Tripal finds the importer automatically, but for unit testing we must include it to our test class explicitly.  Second, we must initialize an instance of our importer class. Aftewards we can perform any tests to ensure our loader executed properly.  The following function provides an example for setup of the loader for testing:

.. code-block:: php

  private function run_loader(){

    // Load our importer into scope.
    module_load_include('inc', 'tripal_example_importer', 'includes/TripalImporter/ExampleImporter');

    // Create an array of arguments we'll use for testing our importer.
    $run_args = [
      'analysis_id' => $some_analysis_id,
      'cvterm' => $some_cvterm_id
    ];
    $file = ['file_local' => __DIR__ . '/../data/exampleFile.txt'];

    // Create a new instance of our importer.
    $importer = new \ExampleImporter();
    $importer->create($run_args, $file);

    // Before we run our loader we must let the TripalImporter prepare the
    // files for us.
    $importer->prepareFiles();
    $importer->run();
  }

.. note::

  We highly recommend you make use of database transactions in your tests, especially when running loaders.  Simply add ``use DBTransaction;`` at the start of your test class.  Please see the `Tripal Test Suite documentation for more information <https://tripaltestsuite.readthedocs.io/en/latest/>`_.


Test Data
^^^^^^^^^
You will note that our test has a few requirements.  It needs the features (test_gene_1 and test_gene_2) and the analysis.  You could load this data separately, but then the test will fail for new developers until they also create the features and analysis.

Instead, you can use **Chado Factories** to quickly and easily provide unique features, analyses, or whatever else you may need for your test to run.  This data is created for each test, and, if wrapped in a DBTransaction, is removed when the test finishes.

.. note::
  To learn more about Chado Factories, please see the `Tripal Test Suite documentation <https://tripaltestsuite.readthedocs.io/en/latest/>`_.


We could use factories for ``$some_cvterm_id`` as well, but because our form actually forces the user to choose from predefined cvterms, let's pick one of those instead.



Using factories, our test might look something like this now.

  .. code-block:: php

    private function run_loader(){
      $some_analysis_id = factory('chado.analysis')->create()->analysis_id;
      factory('chado.feature')->create(['uniquename' => 'test_gene_1', 'name' => 'test_gene_1']);
      factory('chado.feature')->create(['uniquename' => 'test_gene_2', 'name' => 'test_gene_2']);

      $some_cvterm_id = chado_get_cvterm(['id' => 'SO:0000235']);

      $run_args =
        'analysis_id' => $some_analysis_id,
        'cvterm' => $some_cvterm_id
      ];
      $file = ['file_local' => __DIR__ . '/../data/exampleFile.txt'];

      module_load_include('inc', 'tripal_example_importer', 'includes/TripalImporter/ExampleImporter');
       $importer = new \ExampleImporter();
       $importer->create($run_args, $file);
       $importer->prepareFiles();
       $importer->run();
    }


Writing the Test
^^^^^^^^^^^^^^^^

Below is an example test.  Note that it runs the importer, then uses the values in the ``run_loader`` method to retrieve the property that loader inserted.

.. code-block:: php

  /**
   * Test that the loader runs and adds a property.
   * The test file will associate "blue" with test_gene_1
   *
   * @group test_ExampleImporter
   * @group chado
   *
   */
  public function test_ExampleImporter_adds_test_props(){

    $this->run_loader();

    $type = chado_get_cvterm(['id' => 'SO:0000235'])->cvterm_id;

    $query = db_select('chado.featureprop', 'fp');
    $query->join('chado.feature', 'f', 'f.feature_id = fp.feature_id');
    $query->condition('f.uniquename', 'test_gene_1');
    $query->condition('fp.type_id', $type);
    $query->fields('fp', ['value']);
    $result = $query->execute()->fetchField();
    $this->assertEquals('blue', $result);


  }

Note that the test name begins with ``test_``.  This tells Tripal Test Suite that this function is a test and should be run as such.  The test itself runs the loader, then queries the db to retrieve the ``featureprop`` record that should have been created in the first line of the example file.  It then uses an **assertion** to check that the value retrieved is, in fact, the same value in the test file.  PHPUnit has many assertions: please `read the documentation <https://phpunit.de/manual/>`_ for more information on the many assertion types available.

Note also that we use the ``@group`` tag: this lets us run specific subsets of tests.

To run the test from the command line, we can ``phpunit --group test_exampleImporter`` to **just run tests associated with this importer!**  This is very helpful if you have many tests.

Once the test is passing, we can refactor the importer as much as we'd like.  So long as the test passes, we have confidence that our refactoring has not broken the code.
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

No branches or pull requests

1 participant