tests.rst 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. .. _tests:
  2. Unit Tests for Tripal
  3. =======================
  4. This guide is for developers looking to contribute code to the core Tripal project. It introduces the testing philosophy and guidelines for Tripal core. Tripal uses Tripal Test Suite, which brings bootstraps your Tripal site for PHPUnit. It also provides conveniences like name spacing, seeders, transactions, and data factories.
  5. Tripal Test Suite
  6. -------------------
  7. For a basic introduction of Tripal Testing, please see the `Test Suite documentation <https://tripaltestsuite.readthedocs.io/en/latest/>`_.
  8. Installation
  9. ~~~~~~~~~~~~~~
  10. After cloning the `Tripal Github repo <https://github.com/tripal/tripal>`_, you will need to install the developer dependencies required to run tests locally. To do this, you'll need to `install Composer <https://getcomposer.org/doc/00-intro.md>`_, and then execute ``composer install`` in your project root.
  11. Remember to run ``composer update`` to update Tripal TestSuite before writing and running new tests. This is especially important when running pull requests that contribute unit tests. If tests are passing on the Travis environment but not on your machine, running composer update might resolve the problem.
  12. Testing criteria
  13. -----------------
  14. For facilitate accepting your pull requests, your code should include tests. The tests should meet the following guidelines:
  15. * All tests pass
  16. * Tests pass in all environments (Travis)
  17. * Tests don't modify the database (use transactions or clean up after yourself)
  18. * Tests are properly organized (see organization section below)
  19. * Tests run quietly
  20. Test organization
  21. ------------------
  22. Tests should be placed in ``tests/``. This root directory contains the following files:
  23. * ``bootstrap.php`` - Test directory configuration. Don't modify this.
  24. * ``DatabasSeeders/`` - `Database seeders <https://github.com/statonlab/TripalTestSuite#database-seeders>`_, for filling Chado with permanent test data.
  25. * ``DataFactory.php`` - `Data factories <https://github.com/statonlab/TripalTestSuite#factories>`_, for providing test-by-test Chado data.
  26. * ``example.env`` - An example environment file. Configure this to match your development site and save as ``.env``. Read more here: https://tripaltestsuite.readthedocs.io/en/latest/environment.html
  27. Tests must end with ``Test.php`` to be recognized by PHPUnit. The tests themselves should be organized by submodule, and category.
  28. Submodules
  29. ~~~~~~~~~~~
  30. * tripal
  31. * tripal_bulk_loader
  32. * tripal_chado
  33. * tripal_chado_views
  34. * tripal_daemon
  35. * tripal_ds
  36. * tripal_ws
  37. Categories
  38. ~~~~~~~~~~
  39. * API
  40. * theme
  41. * views
  42. * drush
  43. * fields
  44. * entities
  45. * admin
  46. * loaders
  47. So for example, tests for the file ``tripal/api/tripal.jobs.api.inc`` should go in ``tests/tripal/api/TripalJobsAPITest.php``. tests that don't fit in any of these categories should be placed in ``tests/[submodule]/``.
  48. In order for tests to run locally, you'll need an environmental file ``tests/.env`` with the project root, base url, and locale. See ``tests/example.env`` for an example.
  49. Writing tests
  50. --------------
  51. When doing test driven development, you might be running tests over and over. To speed you along, you can assign your tests a unique ``@group`` tag, ie ``@group failing``. Then specify your novel group when you run ``phpunit``, ie ``phpunit --group failing``.
  52. You should also tag your test with relevant groups. For example, our Tripal Chado API tests should be tagged with ``@group api``. We don't tag it with ``@group chado`` because it is in the *testsuite* (the submodule folder) Chado.
  53. If your test is related to a specific issue on the Tripal repo, thats great! You can use the ``@ticket`` tag to link it: ie, ``@ticket 742`` for issue number 742.
  54. Defining the test class
  55. ------------------------
  56. Once you've identified where your test will go, we can start writing our test.
  57. Tripal Test suite provides a convenient way to start writing a test class: ``tripaltest make:test TestName``. From the project root, our example ``./vendor/bin/tripaltest make:test tripal_chado/api/TripalChadoOrganismAPITest``. This will generate a test stub file with name spacing.
  58. The test class file should extend ``StatonLab\TripalTestSuite\TripalTestCase`` instead of `TestCase` to take advantage of the Tripal Test Suite tools. For example, to wrap our tests in a database transaction (so we can indiscriminately insert and modify without having to revert consider how to clean up the database after), we use ``StatonLab\TripalTestSuite\DBTransaction;``. Your test class name should match the file.
  59. .. code-block:: php
  60. use StatonLab\TripalTestSuite\DBTransaction;
  61. use StatonLab\TripalTestSuite\TripalTestCase;
  62. class TripalChadoOrganismAPITest extends TripalTestCase {
  63. use DBTransaction;
  64. }
  65. You typically will want at least one test per public method in your file or class. In the below test class, I define a single test: ``test_tripal_get_organism()``. The test should start with `test_`, otherwise it wont run by default in PHPUnit (you can also declare that it is a test in the method documentation using ``@test``.
  66. An ideal test operates *independently* of other tests: by default, unit tests run in random order. How, then, do we provide our test with relevant data? We use **Factories**, which you can read about on in the `Tripal Test Suite documentation <https://tripaltestsuite.readthedocs.io/en/latest/factories.html>`_. In the below example, we create an organism with known information, and assert that we can retrieve it with the Chado API functions.
  67. .. code-block:: php
  68. namespace Tests\tripal_chado\api;
  69. use StatonLab\TripalTestSuite\DBTransaction;
  70. use StatonLab\TripalTestSuite\TripalTestCase;
  71. class TripalChadoOrganismAPITest extends TripalTestCase {
  72. use DBTransaction;
  73. /**
  74. * Test tripal_get_organism.
  75. *
  76. * @group api
  77. */
  78. public function test_tripal_get_organism() {
  79. $genus_string = 'a_genius_genus';
  80. $species_string = 'fake_species';
  81. $organism = factory('chado.organism')->create([
  82. 'genus' => $genus_string,
  83. 'species' => $species_string,
  84. ]);
  85. $results = [];
  86. $results[] = tripal_get_organism(['organism_id' => $organism->organism_id]);
  87. $results[] = tripal_get_organism([
  88. 'genus' => $genus_string,
  89. 'species' => $species_string,
  90. ]);
  91. foreach ($results as $result) {
  92. $this->assertNotFalse($result);
  93. $this->assertNotNull($result);
  94. $this->assertObjectHasAttribute('genus', $result);
  95. $this->assertEquals($genus_string, $result->genus);
  96. }
  97. }
  98. public function test_tripal_get_organism_fails_gracefully() {
  99. $result = tripal_get_organism([
  100. 'genus' => uniqid(),
  101. 'species' => uniqid(),
  102. ]);
  103. $this->assertNull($result);
  104. }
  105. }
  106. Testing quietly
  107. ~~~~~~~~~~~~~~~~
  108. Code may output errors when failing intentionally, or as part of job progress. This can clutter the test environment, so you should wrap the offending methods. If the output goes to standard out, you can use ``ob_start()`` and ``ob_end_clean()``.
  109. .. code-block:: php
  110. ob_start();//dont display the job message
  111. $bool = tripal_chado_publish_records($values);
  112. ob_end_clean();
  113. If the message comes from the Tripal error reporter, you must use ``"TRIPAL_SUPPRESS_ERRORS=TRUE"`` to suppress the Tripal error reporter message.
  114. .. code-block:: php
  115. /**
  116. * Test chado_publish_records returns false given bad bundle.
  117. *
  118. * @group api
  119. */
  120. public function test_tripal_chado_publish_records_false_with_bad_bundle() {
  121. putenv("TRIPAL_SUPPRESS_ERRORS=TRUE");//this will fail, so we suppress the tripal error reporter
  122. $bool = tripal_chado_publish_records(['bundle_name' => 'never_in_a_million_years']);
  123. $this->assertFalse($bool);
  124. putenv("TRIPAL_SUPPRESS_ERRORS");//unset
  125. }