Преглед изворни кода

Merge pull request #29 from tripal/testing

Tripal JBrowse Management Testing
Lacey-Anne Sanderson пре 5 година
родитељ
комит
06c98d4f8c

+ 2 - 0
.gitignore

@@ -5,3 +5,5 @@ vendor/
 _build/
 
 .env
+
+tests/_build

+ 21 - 3
.travis.yml

@@ -8,13 +8,31 @@ services:
   - docker
 
 env:
-  - DRUPAL_ROOT=/var/www/html
+  - DRUPAL_ROOT=/var/www/html JBROWSE_ROOT=/var/www/html/jbrowse IS_TRAVIS=TRUE CC_TEST_REPORTER_ID=1a35bfa282bdb226287eee73c3eb1fdb61f1509117f55417135081624a0366be
 
 before_script:
   - docker pull statonlab/tripal3
+  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
+  - chmod +x ./cc-test-reporter
+  - ./cc-test-reporter before-build --debug
+  - GIT_BRANCH=$TRAVIS_PULL_REQUEST_BRANCH
+  - GIT_COMMIT_SHA=$TRAVIS_PULL_REQUEST_SHA
 
 script:
   - docker run -it -d --rm --name tripal -v "$(pwd)":/modules/tripal_jbrowse statonlab/tripal3
   - sleep 30 # We pause here so postgres and apache complete booting up
-  - docker exec -it tripal drush pm-enable -y tripal_jbrowse
-  - docker exec -it tripal bash -c "cd /modules/tripal_jbrowse && composer install && DRUPAL_ROOT=/var/www/html ./vendor/bin/phpunit"
+  ## Install JBrowse
+  - docker exec -it tripal bash -c 'sudo yum -y groupinstall "Development Tools"'
+  - docker exec -it tripal bash -c 'sudo yum -y install zlib-devel perl-ExtUtils-MakeMaker'
+  - docker exec -it tripal bash -c 'curl -L -O https://github.com/GMOD/jbrowse/releases/download/1.16.6-release/JBrowse-1.16.6.zip'
+  - docker exec -it tripal bash -c 'unzip JBrowse-1.16.6.zip && sudo mv JBrowse-1.16.6 /var/www/html/jbrowse && cd /var/www/html && sudo chown `whoami` jbrowse'
+  - docker exec -it tripal bash -c 'cd /var/www/html/jbrowse && ./setup.sh'
+  ## Setup XDebug for Code Coverage
+  - docker exec -it tripal yum install -y php-pecl-xdebug.x86_64
+  ## Install tripal_jbrowse package.
+  - docker exec -it tripal drush pm-enable -y tripal_jbrowse tripal_jbrowse_mgmt
+  ## Run Tests.
+  - docker exec -it tripal bash -c "cd /modules/tripal_jbrowse && composer install && DRUPAL_ROOT=/var/www/html ./vendor/bin/phpunit --coverage-clover ./clover.xml"
+
+after_script:
+  - ./cc-test-reporter after-build clover.xml --debug -t clover -p /var/www/html/sites/all/modules/custom/tripal_jbrowse --exit-code $TRAVIS_TEST_RESULT

+ 7 - 0
phpunit.xml

@@ -12,4 +12,11 @@
       <directory suffix="Test.php">tests</directory>
     </testsuite>
   </testsuites>
+  <filter>
+     <whitelist addUncoveredFilesFromWhitelist="true">
+       <file>./tripal_jbrowse_mgmt/tripal_jbrowse_mgmt.module</file>
+       <directory suffix=".inc">./tripal_jbrowse_mgmt</directory>
+       <directory suffix=".php">./tripal_jbrowse_mgmt</directory>
+     </whitelist>
+   </filter>
 </phpunit>

+ 279 - 0
tests/tripal_jbrowse_mgmt/ApiTest.php

@@ -0,0 +1,279 @@
+<?php
+namespace Tests\tripal_jbrowse_mgmt;
+
+use StatonLab\TripalTestSuite\DBTransaction;
+use StatonLab\TripalTestSuite\TripalTestCase;
+use Faker\Factory;
+
+class ApiTest extends TripalTestCase {
+  // Uncomment to auto start and rollback db transactions per test method.
+  use DBTransaction;
+
+  /**
+   * Tests the Settings API.
+   *
+   * Specifically tripal_jbrowse_mgmt_save_settings()
+   * and tripal_jbrowse_mgmt_get_settings().
+   */
+  public function testSettings() {
+
+    $test_settings = [
+      'bin_path' => 'test/fake/path',
+	    'link' => 'test/fake/path',
+	    'data_dir' => 'test/fake/path',
+	    'menu_template' => [],
+    ];
+
+    tripal_jbrowse_mgmt_save_settings($test_settings);
+    $retrieved = tripal_jbrowse_mgmt_get_settings();
+
+    // Check that all the expected settings are available.
+    $expected = ['bin_path', 'link', 'data_dir', 'menu_template'];
+    foreach ($expected as $expected_key) {
+      $this->assertArrayHasKey($expected_key, $retrieved,
+        "Retrieved settings do not contain $expected_key");
+
+      // Check that the settings match if provided in test.
+      if (isset($test_settings[$expected_key])) {
+        $this->assertEquals(
+          $test_settings[$expected_key],
+          $retrieved[$expected_key],
+          "The retrieved value for $expected_key does not match what we set."
+        );
+      }
+    }
+  }
+
+  /**
+   * Test Instance Create-Retrieve-Update-Delete.
+   */
+  public function testInstanceCRUD() {
+    putenv("TRIPAL_SUPPRESS_ERRORS=TRUE");
+
+    $organism = factory('chado.organism')->create();
+
+    // Full Fake Instance Details.
+    $faker = Factory::create();
+    $testdata = [
+      'organism_id' => $organism->organism_id,
+      'title' => $faker->words(3, TRUE),
+      'description' => $faker->sentence(25, TRUE),
+      'created_at' => $faker->unixTime(),
+      'file' => '/path/to/fake/file',
+    ];
+
+    // Check we cannot create a JBrowse instance without an organism.
+    $noOrganism = $testdata;
+    unset($noOrganism['organism_id']);
+    $id = tripal_jbrowse_mgmt_create_instance($noOrganism);
+    $this->assertFalse($id,
+      "Created an instance without an organism_id!?!");
+
+    // Now try to create an instance with all the data.
+    $id = tripal_jbrowse_mgmt_create_instance($testdata);
+    $this->assertNotFalse($id,
+      "Unable to create instance.");
+
+    // Try to retrieve the instance we just created.
+    $retrieved_instance = tripal_jbrowse_mgmt_get_instance($id);
+    $this->assertNotFalse($id, "We did not retrieve an instance?");
+    $this->assertEquals($id, $retrieved_instance->id,
+      "We retrieved a different instance then we asked for?");
+    $this->assertEquals(
+      $testdata['organism_id'], $retrieved_instance->organism_id,
+      "Retreived the same instance but the organism is not correct?");
+
+    // Change the title and test the instance was updated.
+    $new_title = $testdata;
+    $testdata['title'] = 'NEW FAKE TITLE ' . uniqid();
+    $success = tripal_jbrowse_mgmt_update_instance($id, $new_title);
+    $this->assertNotFalse($success, 'Unable to update instance title.');
+    $retrieved_instance = tripal_jbrowse_mgmt_get_instance($id);
+    $this->assertEquals(
+      $new_title['title'], $retrieved_instance->title,
+      "The title was not updated.");
+
+    // Finally delete him!
+    $success = tripal_jbrowse_mgmt_delete_instance($retrieved_instance);
+    $this->assertNotFalse($success, 'Unable to delete this instance.');
+    $one_more_time = tripal_jbrowse_mgmt_get_instance($id);
+    $this->assertFalse($one_more_time);
+
+    // and delete with numeric id.
+    $success = tripal_jbrowse_mgmt_delete_instance($id);
+    $this->assertNotFalse($success, 'Unable to delete this instance.');
+    // and catch an exception during delete.
+    try {
+      $success = tripal_jbrowse_mgmt_delete_instance('FAKESTRING');
+      // If we get here without an exception then this test should fail.
+      $this->assertTrue(FALSE, "Shouldn't be able to extract instance to delete.");
+    } catch (\Exception $e) {
+        // Not worried since this is expected!
+    }
+
+    putenv("TRIPAL_SUPPRESS_ERRORS");
+  }
+
+  /**
+   * Test Track Create-Retrieve-Update-Delete.
+   */
+  public function testTrackCRUD() {
+
+    // Fake Instance.
+    $faker = Factory::create();
+    $organism = factory('chado.organism')->create();
+    $instance_details = [
+      'organism_id' => $organism->organism_id,
+      'title' => $faker->words(3, TRUE),
+      'description' => $faker->sentence(25, TRUE),
+      'created_at' => $faker->unixTime(),
+      'file' => '/path/to/fake/file',
+    ];
+    $instance_id = tripal_jbrowse_mgmt_create_instance($instance_details);
+    $instance = tripal_jbrowse_mgmt_get_instance($instance_id);
+
+    $path = tripal_jbrowse_mgmt_get_track_list_file_path($instance);
+    $this->assertNotFalse($path,
+      "Unable to retrieve the path to the trackList.json");
+
+    // Fake track details.
+    $testdata = [
+      'label' => $faker->words(2, TRUE),
+      'track_type' => 'CanvasFeatures',
+      'file_type' => 'gff',
+      'created_at' => $faker->unixTime(),
+      'file' => '/path/to/fake/file',
+    ];
+
+    // First retrieve when there are no tracks.
+    $tracks = tripal_jbrowse_mgmt_get_tracks($instance);
+    $this->assertCount(0, $tracks,
+      "There should not be tracks as we just created this instance.");
+
+    // Create tracks.
+    $track_id = tripal_jbrowse_mgmt_create_track($instance, $testdata);
+    $this->assertNotFalse($track_id,
+      "We should have a track created successfully.");
+
+    // Retrieve our newly created track.
+    $track = tripal_jbrowse_mgmt_get_track($track_id);
+    $this->assertNotFalse($track, "Unable to create track.");
+    $this->assertEquals($testdata['label'], $track->label,
+      "The label of our new track didn't match what we submitted.");
+    $this->assertEquals($instance->id, $track->instance_id,
+      "The instance_id of our new track didn't match what we submitted.");
+    $this->assertEquals($instance->organism_id, $track->organism_id,
+      "The organism_id of our new track didn't match what we submitted.");
+
+    // Retrieve track with a condition.
+    $tracks = tripal_jbrowse_mgmt_get_tracks($instance, ['label' => $testdata['label']]);
+    $this->assertCount(1, $tracks, "We were not able to select a track we knew should exist.");
+
+    // Now update it.
+    $new_label = 'NEW LABEL ' . uniqid();
+    $success = tripal_jbrowse_mgmt_update_track($track, ['label' => $new_label]);
+    $this->assertNotFalse($success, "Unable to update track label.");
+    $new_track = tripal_jbrowse_mgmt_get_track($track_id);
+    $this->assertEquals($new_label, $new_track->label,
+      "The label of the track was not updated.");
+
+    // Finally, delete it.
+    $success = tripal_jbrowse_mgmt_delete_track($track_id);
+    $this->assertNotFalse($success, "Unable to delete track.");
+    $success = tripal_jbrowse_mgmt_delete_track($track_id);
+    $this->assertEquals(0, $success, "Deleted a track that doesn't exist?");
+  }
+
+  /**
+   * Test organism-related api functions.
+   */
+  public function testOrganismAPI() {
+
+    // Fake Organism.
+    $faker = Factory::create();
+    $organism = factory('chado.organism')->create();
+
+    $organism_list = tripal_jbrowse_mgmt_get_organisms_list();
+    $this->assertNotCount(0, $organism_list, "There should be at least one organism.");
+    $this->assertArrayContainsObjectValue($organism_list, 'organism_id', $organism->organism_id);
+
+    $organism_name = tripal_jbrowse_mgmt_construct_organism_name($organism);
+    $this->assertRegexp('/'.$organism->genus.'/', $organism_name,
+      "The organism name did not contain the genus.");
+    $this->assertRegexp('/'.$organism->species.'/', $organism_name,
+      "The organism name did not contain the species.");
+
+    $slug = tripal_jbrowse_mgmt_make_slug($organism_name);
+    $this->assertNotRegexp('/ /', $slug,
+      "The organism slug should not contain spaces.");
+  }
+
+  /**
+   * Test Instance Properties Create-Retrieve-Update.
+   */
+  public function testInstanceProperyCRU() {
+
+    // Fake Instance.
+    $faker = Factory::create();
+    $organism = factory('chado.organism')->create();
+    $instance_details = [
+      'organism_id' => $organism->organism_id,
+      'title' => $faker->words(3, TRUE),
+      'description' => $faker->sentence(25, TRUE),
+      'created_at' => $faker->unixTime(),
+      'file' => '/path/to/fake/file',
+    ];
+    $instance_id = tripal_jbrowse_mgmt_create_instance($instance_details);
+
+    $testdata = [
+      $faker->word() => $faker->words(3, TRUE),
+      $faker->word() => $faker->words(2, TRUE),
+      $faker->word() => $faker->words(10, TRUE),
+    ];
+
+    // Create.
+    tripal_jbrowse_mgmt_save_instance_properties($instance_id, $testdata);
+
+    // Retrieve.
+    $properties = tripal_jbrowse_mgmt_get_instance_properties($instance_id);
+    $this->assertIsArray($properties, "Unable to retrieve newly created properties.");
+    $this->assertCount(3, $properties,
+      "There was not the expected count of properties.");
+
+    // Update single property.
+    $property_name = key($testdata);
+    $new_value = 'NEW VALUE '.uniqid();
+    tripal_jbrowse_mgmt_save_instance_property($instance_id, $property_name, $new_value);
+    $retrieved_value = tripal_jbrowse_mgmt_get_instance_property($instance_id, $property_name);
+    $this->assertEquals($new_value, $retrieved_value,
+      "We were unable to update a single property.");
+
+  }
+
+  /**
+   * Test Miscellaneous API functions.
+   */
+  public function testMiscAPI() {
+
+    $track_types = tripal_jbrowse_mgmt_get_track_types();
+    $this->assertIsArray($track_types,
+      "The track types should be an array.");
+
+  }
+  /**
+   * Provide an assertion to check properties of an array of objects.
+   *
+   * For example, if you have an array of organism objects, the following code
+   * would check that one object in the array has an organism_id of 50.
+   * @code $this->assertArrayContainsObjectValue($array, 'organism_id', 50);
+   */
+  private function assertArrayContainsObjectValue($theArray, $attribute, $value)
+  {
+      foreach($theArray as $arrayItem) {
+          if($arrayItem->$attribute == $value) {
+              return true;
+          }
+      }
+      return false;
+  }
+}

+ 43 - 0
tests/tripal_jbrowse_mgmt/ModuleFileTest.php

@@ -0,0 +1,43 @@
+<?php
+namespace Tests\tripal_jbrowse_mgmt;
+
+use StatonLab\TripalTestSuite\DBTransaction;
+use StatonLab\TripalTestSuite\TripalTestCase;
+
+class ModuleFileTest extends TripalTestCase {
+  // Uncomment to auto start and rollback db transactions per test method.
+  // use DBTransaction;
+
+  /**
+   * Tests hook_menu(). Specifically, are all the required keys set.
+   */
+  public function testHookMenu() {
+
+    $menu_items = tripal_jbrowse_mgmt_menu();
+    $this->assertIsArray($menu_items);
+
+    foreach($menu_items as $path => $item) {
+      $this->assertArrayHasKey('title', $item,
+        "$path menu item is missing a title.");
+      $this->assertArrayHasKey('page callback', $item,
+        "$path menu item is missing a page callback.");
+      $this->assertArrayHasKey('access arguments', $item,
+        "$path menu item is missing access arguments.");
+      $this->assertIsArray($item['access arguments'],
+        "$path menu item access arguments must be an array.");
+    }
+  }
+
+  /**
+   * Tests hook_permission(). Specifically, checks format.
+   */
+  public function testHookPerm() {
+    $permissions = tripal_jbrowse_mgmt_permission();
+    $this->assertIsArray($permissions);
+
+    foreach ($permissions as $key => $perm) {
+      $this->assertArrayHasKey('title', $perm,
+        "$key permission is missing a title.");
+    }
+  }
+}

+ 17 - 13
tripal_jbrowse_mgmt/includes/tripal_jbrowse_mgmt.api.inc

@@ -93,7 +93,22 @@ function tripal_jbrowse_mgmt_get_instances($conditions = NULL) {
 function tripal_jbrowse_mgmt_create_instance($data) {
   global $user;
 
-  $instance_id = db_insert('tripal_jbrowse_mgmt_instances')->fields([
+  // Check that required fields are provided.
+  $required = ['organism_id', 'created_at'];
+  foreach ($required as $key) {
+    if (!isset($data[$key])) {
+      tripal_report_error(
+        'tripal_jbrowse_mgmt',
+        TRIPAL_ERROR,
+        'Unable to create instance due to missing :key',
+        [':key' => $key]
+      );
+      return FALSE;
+    }
+  }
+
+  // If they are all present, then insert into the database.
+  return db_insert('tripal_jbrowse_mgmt_instances')->fields([
     'uid' => $user->uid,
     'organism_id' => $data['organism_id'],
     'title' => $data['title'],
@@ -102,11 +117,6 @@ function tripal_jbrowse_mgmt_create_instance($data) {
     'file' => $data['file'],
   ])->execute();
 
-  if (!$instance_id) {
-    return FALSE;
-  }
-
-  return $instance_id;
 }
 
 /**
@@ -171,7 +181,7 @@ function tripal_jbrowse_mgmt_delete_instance($instance) {
 function tripal_jbrowse_mgmt_create_track($instance, $data) {
   global $user;
 
-  $track_id = db_insert('tripal_jbrowse_mgmt_tracks')->fields([
+  return db_insert('tripal_jbrowse_mgmt_tracks')->fields([
     'uid' => $user->uid,
     'instance_id' => $instance->id,
     'organism_id' => $instance->organism_id,
@@ -181,12 +191,6 @@ function tripal_jbrowse_mgmt_create_track($instance, $data) {
     'created_at' => $data['created_at'],
     'file' => $data['file'],
   ])->execute();
-
-  if (!$track_id) {
-    return FALSE;
-  }
-
-  return $track_id;
 }
 
 /**