Allow tests to require and test existance of contrib modules

Dave Reid - December 6, 2008 - 03:03
Project:Drupal
Version:7.x-dev
Component:simpletest.module
Category:task
Priority:critical
Assigned:Dave Reid
Status:closed
Issue tags:API clean-up, Favorite-of-Dries
Description

As I proposed in http://groups.drupal.org/node/17325:

I am writing a test for one of my contrib modules that has a feature that is enabled when another contrib module (we'll call it OtherModule) is enabled. I want other people other than myself to be able to run the entire test suite, but what if they didn't have OtherModule installed or even present in their Drupal installation? The test is going to fail spectacularly in that case. So I ended up wrapping that test case class in an if statement:

<?php
if (($file = db_result(db_query("SELECT filename FROM {system} WHERE type = 'module' AND name = 'othermodule'"))) && file_exists($file)) {
  class
MyModuleOtherModuleIntegrationTestCase extends DrupalWebTestCase {
     ...
  }
}
?>

I re-used the idea from module_load_include and drupal_get_filename to check if the current module is present in the {system} table and that the file also exists. Keep in mind the check for file_exists is necessary since Drupal doesn't remove records from {system} of deleted files/modules.

Going through this got me thinking...what if I could just specify that this test requires a module using getInfo()? This will admittedly not be very useful for any of the core tests, since we are assured they will always exist. I think this might be useful for contrib module tests that need to test integration with another (optional) contrib module. The implementation in getInfo() would look like the following:

<?php
class MyModuleOtherModuleIntegrationTestCase extends DrupalWebTestCase {
  function
getInfo() {
    return array(
     
'name' => t('OtherModule integration'),
     
'description' => t('Test MyModule integration with OtherModule.'),
     
'group' => t('MyModule'),
     
'requires' => array('othermodule'),
  }
  ...
}
?>

#1

Dave Reid - December 6, 2008 - 03:08
Status:active» needs review

Here's the patch to simpletest.module along with a 'dummy' .test file to place in modules/simpletest/tests so you can see how a test that requires another [missing] contrib module will fail with the patch, and how it will not show/run the test with the patch.

I must reiterate that this will not be useful for core tests, but we need to start thinking about contrib tests and sub-module contrib tests.

AttachmentSizeStatusTest resultOperations
343502-simpletest-required-modules-D7.patch1.28 KBIdleFailed: 10514 passes, 0 fails, 1 exceptionView details | Re-test
343502.test1017 bytesIgnoredNoneNone

#2

dmitrig01 - December 14, 2008 - 16:20

Can you post the test as a .txt file? it's not letting me access it as a .test.

#3

Dave Reid - December 14, 2008 - 18:03

Oh sorry, that's weird. Here you go dmitrig01.

AttachmentSizeStatusTest resultOperations
343502.test.txt1017 bytesIgnoredNoneNone

#4

Dave Reid - January 6, 2009 - 21:39

#5

Dries - January 7, 2009 - 12:25

This looks like a valid use-case to me, and system tests (tests between modules) is something we want to enable and encourage.

Should we use the same terminology used in .info files? That is 'dependencies' rather than 'requires'?

#6

Dries - January 7, 2009 - 12:25

This looks like a valid use-case to me, and system tests (tests between modules) is something we want to enable and encourage.

Should we use the same terminology used in .info files? That is 'dependencies' rather than 'requires'?

#7

Dave Reid - January 7, 2009 - 18:35

Yeah, that would probably be best, I'll re-roll shortly.

#8

Dave Reid - January 11, 2009 - 19:31

Changed 'requires' to 'dependencies'.

AttachmentSizeStatusTest resultOperations
343502-simpletest-required-modules-D7.patch1.21 KBIdleFailed: 9344 passes, 1 fail, 0 exceptionsView details | Re-test
343502.test.txt1 KBIgnoredNoneNone
343502.test1 KBIgnoredNoneNone

#9

Dries - January 12, 2009 - 08:32

#320451: Clean up some modules code is related -- might be worth a look. I'd prefer to get #320451 in first.

#10

System Message - January 29, 2009 - 05:15
Status:needs review» needs work

The last submitted patch failed testing.

#11

Dave Reid - January 29, 2009 - 14:21
Status:needs work» needs review

Not sure why the 'File naming' test has a fail, it's completely unrelated and no test code is actually touched by this patch. *shrugs* The same test passes on my local install.

Anyway, I re-rolled to fix a 1 line offset and to give the testing bot a chance to redeem itself.

AttachmentSizeStatusTest resultOperations
343502-simpletest-required-modules-D7.patch1.21 KBIdleFailed: Failed to apply patch.View details | Re-test

#12

alexanderpas - February 12, 2009 - 03:41

can we have a test for this testclause???

something like dependent on non-existing-module and then $this->assertTrue(FALSE, 'dependent code failure');

otherwise, nice work

#13

Dave Reid - February 12, 2009 - 18:36

Sure thing! Easy enough to do. :)

AttachmentSizeStatusTest resultOperations
343502-simpletest-required-modules-D7.patch2.3 KBIdleFailed: Failed to apply patch.View details | Re-test

#14

sun - February 13, 2009 - 01:42

subscribing

#15

dbabbage - February 13, 2009 - 04:14

Great idea, very useful. I have two suggestions, one which I'll post now, the other one once I've tested what I'm saying to be sure it is right!

Suggestion 1: Rather than just excluding the test, I think it would be useful to have some sort of feedback to the user that optional tests have not run due to XX optional module not being installed. Otherwise, the person running the tests may be unaware they have broken a piece of functionality that cannot be tested with the currently suitable tests. Does not look like the current patch provides for this...

#16

Dave Reid - February 13, 2009 - 04:16

I think the main idea behind this was to allow for integration tests that you only want to run if the module is installed, in which case if it's not, should not be displayed or even run. I'll look into that, but I fear it will make this simple path a little less simple.

#17

dbabbage - February 13, 2009 - 05:07

OK.
I believe the query needs to be:

<?php
($file = db_result(db_query("SELECT filename FROM {system} WHERE type = 'module' AND name = 'othermodule' AND status ='1'")))
?>

Because currently, the query will return modules that are installed, whether or not they are enabled.

My other suggestion above does complicate the patch, and perhaps it would be better as a separate issue. I like small patches.

#18

dbabbage - February 13, 2009 - 05:05

Oh, and just noticed you will also need to change the namespace in the test, because this conflicts with my new Drupal stealth module I am about to upload to CVS, which is already using the name module_that_does_not_exist.

;)

#19

Dave Reid - February 13, 2009 - 05:56

dbabbage, We don't need to check status = 1 because the module doesn't need to be enabled in the system that runs the tests. We just need to check that the module actually exists because the test itself needs to run parent::setUp('othermodule') (inside it's own setUp()) to install and enable it. For example,

<?php
class OtherModuleIntegrationUnitTest extends DrupalWebTestCase {
  function
getInfo() {
    return array(
     
'title' => t('othermodule test'),
     
'description' => t('Tests integration with other contrib modules.'),
     
'group' => t('othermodule'),
     
'dependencies' => array('required_contrib_module', 'another_required_contrib_module'),
    );
  }

  function
setUp() {
   
parent::setUp('required_contrib_module', 'another_required_contrib_module');
  }

  function
testSomething() {
    ...
  }
}
?>

#20

dbabbage - February 13, 2009 - 06:38

Ah ok, I am showing my ignorance regarding writing tests then. Move on, nothing to see here. :)

#21

boombatower - February 16, 2009 - 07:27

So then use module_exists() ?

#22

Dave Reid - February 16, 2009 - 07:46
Status:needs review» needs work

Can't use module_exists because of the scenario:

A test requires module_a that you have available in your Drupal install, but not installed or enabled. You still should be able to run the test that requires module_a.
But using module_exists will fail during the SimpleTest selection form since the module is not enabled.

I could probably help reduce the code using drupal_get_filename() instead of manually checking the system table.

#23

Dave Reid - February 16, 2009 - 07:52
Status:needs work» needs review

Revised patch using drupal_get_filename().

AttachmentSizeStatusTest resultOperations
343502-simpletest-required-modules-D7.patch2.2 KBIdleFailed: 10609 passes, 1 fail, 0 exceptionsView details | Re-test

#24

System Message - February 16, 2009 - 08:20
Status:needs review» needs work

The last submitted patch failed testing.

#25

Dave Reid - February 16, 2009 - 08:26
Status:needs work» needs review

Testbot failure on #4 (user picture tests). Requesting retest.

#26

System Message - March 13, 2009 - 08:40
Status:needs review» needs work

The last submitted patch failed testing.

#27

Dave Reid - March 14, 2009 - 03:16
Status:needs work» needs review

Errant GD testbot error...resetting status.

#28

deviantintegral - May 16, 2009 - 20:49
Status:needs review» needs work

This no longer applies as instantiating each class was removed in #376129: Change getInfo() to a static method for performance. Do we want to re-implement loading the classes so we can call getInfo(), or find some other way of describing test dependancies?

#29

Dave Reid - May 26, 2009 - 01:38
Status:needs work» needs review

Rerolled using the new way $info = call_user_func(array($class, 'getInfo'));.

AttachmentSizeStatusTest resultOperations
343502-simpletest-required-modules-D7.patch1.97 KBIdleFailed: Failed to apply patch.View details | Re-test

#30

mr.baileys - May 26, 2009 - 10:10
Status:needs review» needs work

Some comments after reviewing the patch, applying it and playing around with it:

  1. +      'title' => t('Testing dependent module test'),
    should be 'name' instead of 'title'
  2. I like dbabbage suggestion of having visual feedback when tests are skipped, but I understand this might complicate this patch. Would it be easier to tinker with simpletest_get_all_tests and have it return an additional field called "disabled" or something, and then grey out the checkbox on the SimpleTest submit form (so users are aware of the test and see that it is disabled/skipped)? Or would that be equally complex? Personally, I just hate the fact that there is no trace of the test when the dependencies are missing...

I tried all kinds of dependency combinations and it consistently worked as expected, and the logic looks sound to me...

#31

boombatower - May 26, 2009 - 15:06

If you want to mess with simpletest_get_all_tests() please wait for #449198: SimpleTest: Clean up test loading and related API. From the looks of it that might be a good idea.

#32

Dave Reid - July 9, 2009 - 03:06

Will reroll shortly.

#33

sun - September 10, 2009 - 17:04
Category:feature request» task
Priority:normal» critical
Issue tags:+API clean-up

This is required to make any sense for unit tests in D7 contrib.

#34

sun - October 6, 2009 - 01:50
Status:needs work» needs review

Crazy re-ro-re-roll.

AttachmentSizeStatusTest resultOperations
drupal.testing-dependencies.patch3.21 KBIdlePassed: 13668 passes, 0 fails, 0 exceptionsView details | Re-test

#35

Dave Reid - October 7, 2009 - 02:47
Status:needs review» reviewed & tested by the community

Looks good and tested. Crazy that I did not know about continue statement accepting a the number of levels to skip! Learn something new every day.

#36

Dries - October 8, 2009 - 15:32
Status:reviewed & tested by the community» fixed

Committed to CVS HEAD. Thanks!

#37

System Message - October 22, 2009 - 15:40
Status:fixed» closed

Automatically closed -- issue fixed for 2 weeks with no activity.

 
 

Drupal is a registered trademark of Dries Buytaert.