SlideShare uma empresa Scribd logo
1 de 35
Baixar para ler offline
CONTINUOUS INTEGRATION
                               Automatically Install, Test, and Deploy Your Drupal Site




Wednesday, December 16, 2009
Testing and Drupal

                The focus of Drupal 7 has largely been on automated testing and
                Drupal adopted SimpleTest as its test framework of choice.

                Major Drupal 6 modules are starting to get unit tests, but their
                correctness varies.

                Regardless, it’s still easy to write your own unit tests.




Wednesday, December 16, 2009
SimpleTest

                SimpleTest is a testing framework that has been adopted for use
                in Drupal core and contrib.

                Drupal 7 core is automatically tested using the PIFR module and
                testing slaves.

                We’ll talk later about getting SimpleTests running automatically
                as part of our Hudson continuous integration framework.



Wednesday, December 16, 2009
Running Tests

                SimpleTest is a contributed module for Drupal 6. It is in Drupal
                7 core, and it also happens to be part of the Pressflow
                distribution’s core set of modules.

                To run tests, the SimpleTest module must be enabled. (Our
                install profile turns it on by default.) Then you can head to /
                admin/build/testing to see all the available tests.




Wednesday, December 16, 2009
The SimpleTest Interface


                Each test shown in the
                SimpleTest administrative
                interface is an instance of the
                DrupalWebTestCase class.
                Each of these tests may
                contain multiple assertions.




Wednesday, December 16, 2009
Running Tests


                For each assertion in a test,
                SimpleTest will log whether
                each passed or failed, along
                with any PHP exceptions that
                happen along the way.




Wednesday, December 16, 2009
Testing Workflow


                Ideally, SimpleTests should all be run prior to a commit so that
                we’re not relying on Hudson to find errors in unit tests.

                As of right now, quite a few contributed modules have test
                failures.




Wednesday, December 16, 2009
Writing SimpleTests

                SimpleTest looks for .test files. They should be placed inside a
                tests folder in your module’s folder. (The modules for Drupal
                7’s tests, and the backported block tests for Pressflow are located
                in the <htdocs>/modules/simpletest/tests.)

                Each .test file may contain one or more classes that extend
                DrupalWebTestCase.




Wednesday, December 16, 2009
DrupalWebTestCase

                The DrupalWebTestCase (hereafter DWTC) class defines a
                number of extra helper methods besides the ones provided by
                SimpleTest and also defines a Drupal-specific default setup and
                teardown behavior.

                You can find the definition for this class at
                drupal_web_test_case.php inside the simpletest folder.




Wednesday, December 16, 2009
Your Test Classes

                Each class that inherits from DWTC should provide an
                implementation of the DrupalWebTestCase::getInfo() method:
              function getInfo() {
                return array(
                    'name' => t('RSS and XML formatting tests'),
                    'description' => t('Tests for the format_rss_item() and format_xml_elements()
            functions.'),
                    'group' => t('System'),
                 );
              }



                This information shows up on the SimpleTest admin screen.


Wednesday, December 16, 2009
Your Tests



                In addition to getInfo(), you must create a least one testing
                method. SimpleTest will run any public methods whose names
                begin with “test”.




Wednesday, December 16, 2009
Behind the Scenes

                So how does SimpleTest work without disturbing your local
                database? The real magic happens in the
                DrupalWebTestCase::setUp() method. That method creates a
                new random numerical prefix and then uses Drupal’s database
                prefixing feature to install a new, empty copy of Drupal with the
                default install profile using the random database prefix.

                It also creates a temporary files directory (also prefixed with the
                random number) in the current files directory.


Wednesday, December 16, 2009
Behind The Scenes, Cont’d

                Although it doesn’t show it as a parameter, ::setUp() will also
                take a variable number of extra arguments as modules that should
                be enabled in addition to those that come with the default profile.

                Since block.module is enabled in the default install profile, for
                example, BlockTestCase doesn’t have to call setUp() with any
                extra arguments. However, CCK’s tests need to look in the
                database, and so they need at least the content and text CCK
                modules, and the schema module to examine DB schema.



Wednesday, December 16, 2009
Looking At Tests
                Here’s the BlockTestCase from block.test:
            class BlockTestCase extends DrupalWebTestCase {
                public static function getInfo() {
                    return array(
                         'name' => t('Block functionality'),
                         'description' => t('Add, edit and delete custom block.
            Configure and move a module-defined block.'),
                         'group' => t('Block'),
                    );
                }




Wednesday, December 16, 2009
Looking At Tests
                Here’s the BlockTestCase from block.test:
            /**
              * Implementation of setUp().
              */
                function setUp() {
                    parent::setUp();
                    // Create and login user
                    $admin_user = $this->drupalCreateUser(array('administer
            blocks'));
                    $this->drupalLogin($admin_user);
                }


Wednesday, December 16, 2009
Looking At Tests
                Compare that to the CCK ContentCrudTestCase, which is a
                base class that other CCK tests inherit from. Note how the setUp
                () method is set to enable the three modules the test will need.
            class ContentCrudTestCase extends DrupalWebTestCase {
                function setUp() {
                    $args = func_get_args();
                    $modules = array_merge(array('content', 'schema', 'text'),
            $args);
                    call_user_func_array(array('parent','setUp'), $modules);
                    module_load_include('inc', 'content', 'includes/
            content.crud');


Wednesday, December 16, 2009
Basic Assertions


                The main assertions that are built into the UnitTestCase class
                (from which DrupalWebTestCase inherits) are documented at
                http://simpletest.org/api/SimpleTest/UnitTester/
                UnitTestCase.html .




Wednesday, December 16, 2009
DrupalWebTestCase

                DrupalWebTestCase inherits from the SimpleTest library’s
                WebTestCase class, but also adds extra capabilities for accessing
                Drupal pages by URL, setting the logged in user, submitting
                forms with ::drupalPost() and more.

                You can read about these functions at http://drupal.org/node/
                265762 .




Wednesday, December 16, 2009
Test Types
                 Sometimes you will want to create purely functional tests, as in
                 one I wrote for D7 HEAD to test format_rss_item. This just
                 tests the validity of a regular expression for several common
                 possible XML tags.
            function testElementNameRegex() {
              $regex = '/^[w:][w-:]*$/';


                $this->assertEqual(preg_match($regex,   'i<3badlyformattedtags'), 0,
                  t('XML Element Regex is valid'));
                $this->assertEqual(preg_match($regex,   'georss:point'), 1, t('XML Element Regex is valid'));
                $this->assertEqual(preg_match($regex,   ' not:valid'), 0, t('XML Element Regex is valid'));
                $this->assertEqual(preg_match($regex,   '-not-so-valid'), 0, t('XML Element Regex is valid'));
            }




Wednesday, December 16, 2009
Test Types
                Most of your tests will involve using APIs, such as this test that
                tests the format_rss_item() call to make sure it escapes XSS.
            function testXSS() {
              $sanitized_title = check_plain($this->getRSSTitle());
              $sanitized_link = check_url($this->getRSSLink());
              $sanitized_description = check_plain($this->getRSSDescription());


              $output = format_rss_item($this->getRSSTitle(), $this->getRSSLink(),
            $this->getRSSDescription(), array());


                $simplexml_result = simplexml_load_string($output);




Wednesday, December 16, 2009
Test Types
                Most of your tests will involve using APIs, such as this test that
                tests the format_rss_item() call to make sure it escapes XSS.
              $this->assertTrue($simplexml_result !== FALSE,
                t('SimpleXML could properly parse the output'));
              $this->assertTrue(strpos($output, $sanitized_title) != FALSE,
                t('XSS attack %title was filtered', array('%title' => $this-
            >getRSSTitle())));
              $this->assertTrue(strpos($output, $sanitized_link) != FALSE,
                t('Potentially dangerous URL %link was filtered to
            %sanitized_link',
                  array('%link' => $this->getRSSLink(), '%sanitized_link' =>
            $sanitized_link)));



Wednesday, December 16, 2009
Test-Driven Development

                A major focus of many agile development practices are Test-
                Driven (or Behavior-Driven) Development, whereby unit tests
                are written first to satisfy requirements, and can be continually
                tested as the project progresses.

                Another common thread in doing TDD is to bring tests into bug
                fixes. In many open-source projects, such as jQuery, people ask
                for a test case to demonstrate a bug, and then a new test can be
                written so that the regression never happens again.



Wednesday, December 16, 2009
Running Tests



                Can take a long time, especially if your install profile grows.

                Maybe we can enlist someone else to help out with them.




Wednesday, December 16, 2009
Enter Hudson




Wednesday, December 16, 2009
Installing Hudson

                Debian-based packages are available for Ubuntu

                http://hudson-ci.org/debian/

                You can also run Hudson on Tomcat (beside a SOLR install, for
                example.)

                Hudson on Ubuntu installs your files at /var/lib/hudson/jobs/
                [your job name]/workspace/[top-level SCM package]



Wednesday, December 16, 2009
Getting Hudson Working

                Set up source control

                Set up a build step that installs Drupal

                Set up a build step that runs SimpleTests via the shell script

                Set up JUnit reporting

                Profit?



Wednesday, December 16, 2009
Setting Up Source Control


                Put your SVN (or CVS or Mercurial, etc.) information into
                Hudson and save either credentials and/or a public/private
                keypair

                Set it up to automatically poll your repository for changes if you
                want automatic builds




Wednesday, December 16, 2009
Automatically Installing


                Make a vhost and a hosts entry for your Hudson checkout

                You’ll then want to make a shell script that:

                Runs drush provision to install your site

                Make sure your install profile installs SimpleTest!




Wednesday, December 16, 2009
Automatically Installing

                A sample script:
                #!/bin/bash
                SITE_PATH=/var/lib/hudson/jobs/ProvisionTest/workspace/trunk/
                htdocs
                cd $SITE_PATH
                /bin/drush --root=$SITE_PATH --master_db_host=localhost --
                master_db_user=root --db_type=mysql --db_host=localhost --
                config_path=/etc/apache2/drush-conf --restart_cmd=echo --
                uri=http://drushtest --script_user=hudson --profile=provision
                provision install drushtest




Wednesday, December 16, 2009
Running SimpleTests

                Your install profile must install SimpleTest so that you can use
                the run-tests.sh script to run a number of tests.

                ComputerMinds.co.uk started a SimpleTest patch to output test
                results in the JUnit XML format - this patch will be in Pressflow
                soon and is active on d.o: http://drupal.org/node/602332

                Once you’re running this patch, your Hudson runs will keep
                track of the number of test passes and fails.



Wednesday, December 16, 2009
Running SimpleTests

                The other half of the same script, to handle automatically running
                SimpleTests:

                rm -rf scripts/tests/*.xml
                /usr/bin/php scripts/run-tests.sh --url http://drushtest --xml
                scripts/tests Provision




Wednesday, December 16, 2009
Hudson Results

                Build failure: when Drupal could not be installed, drush will
                return with an error, and Hudson will notify you that the build
                has failed.

                Common causes of this could be parse errors, modules that
                aren’t in source control but are referred to in the install profile,
                and so on.

                Unstable: the installation succeeded, but one or more unit tests
                did not complete successfully.


Wednesday, December 16, 2009
Hudson Results



                Success: Your installation succeeded and all unit tests passed!




Wednesday, December 16, 2009
Unit Testing Recipes

                Test your install profile!

                http://gist.github.com/249754

                This code will let you make a unit test that installs your full install
                profile (in this case, called “provision”) and can then run tests
                against the fully-installed environment.




Wednesday, December 16, 2009
Gotchas
                Drush Provision isn’t _really_ meant to install one site many
                times. If your site’s URL is more than 14 characters, it will fail
                after the 10th install, since it makes a new database each time.

                All those databases will eventually slow your MySQL server
                down, so you manually have to remove them.

                Make sure that you install Provision for both the Hudson /
                Tomcat user and the main web user.

                Make sure you install curl, php-cli and php-curl so that
                SimpleTests can run from the command line.

Wednesday, December 16, 2009

Mais conteúdo relacionado

Mais procurados

Exercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera CymbronExercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera Cymbron
cymbron
 

Mais procurados (20)

Database administration commands
Database administration commands Database administration commands
Database administration commands
 
#29.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
#29.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...#29.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
#29.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
 
#11.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원학원,재직자/실업자교육학원,스프링교육,마이바...
#11.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원학원,재직자/실업자교육학원,스프링교육,마이바...#11.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원학원,재직자/실업자교육학원,스프링교육,마이바...
#11.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원학원,재직자/실업자교육학원,스프링교육,마이바...
 
PL/SQL User-Defined Functions in the Read World
PL/SQL User-Defined Functions in the Read WorldPL/SQL User-Defined Functions in the Read World
PL/SQL User-Defined Functions in the Read World
 
Spring Framework Petclinic sample application
Spring Framework Petclinic sample applicationSpring Framework Petclinic sample application
Spring Framework Petclinic sample application
 
Groovy, Transforming Language
Groovy, Transforming LanguageGroovy, Transforming Language
Groovy, Transforming Language
 
JBoss AS Upgrade
JBoss AS UpgradeJBoss AS Upgrade
JBoss AS Upgrade
 
DbSetup
DbSetupDbSetup
DbSetup
 
My sql tutorial-oscon-2012
My sql tutorial-oscon-2012My sql tutorial-oscon-2012
My sql tutorial-oscon-2012
 
JUnit
JUnitJUnit
JUnit
 
Building node.js applications with Database Jones
Building node.js applications with Database JonesBuilding node.js applications with Database Jones
Building node.js applications with Database Jones
 
Managing Unstructured Data: Lobs in the World of JSON
Managing Unstructured Data: Lobs in the World of JSONManaging Unstructured Data: Lobs in the World of JSON
Managing Unstructured Data: Lobs in the World of JSON
 
Developer's Approach to Code Management
Developer's Approach to Code ManagementDeveloper's Approach to Code Management
Developer's Approach to Code Management
 
Java >= 9
Java >= 9Java >= 9
Java >= 9
 
Web based development
Web based developmentWeb based development
Web based development
 
Java Programming - 03 java control flow
Java Programming - 03 java control flowJava Programming - 03 java control flow
Java Programming - 03 java control flow
 
Developing for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQLDeveloping for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQL
 
Gradle talk, Javarsovia 2010
Gradle talk, Javarsovia 2010Gradle talk, Javarsovia 2010
Gradle talk, Javarsovia 2010
 
Exercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera CymbronExercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera Cymbron
 
Jdbc tutorial
Jdbc tutorialJdbc tutorial
Jdbc tutorial
 

Semelhante a Continuous Integration and Drupal

An introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduceAn introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduce
Ananth PackkilDurai
 
2 second lesson- attributes
2 second lesson- attributes2 second lesson- attributes
2 second lesson- attributes
Mohammad Alyan
 
Drupalcamp Simpletest
Drupalcamp SimpletestDrupalcamp Simpletest
Drupalcamp Simpletest
lyricnz
 

Semelhante a Continuous Integration and Drupal (20)

Junit and testNG
Junit and testNGJunit and testNG
Junit and testNG
 
Simpletest - A beginners guide
Simpletest - A beginners guideSimpletest - A beginners guide
Simpletest - A beginners guide
 
Mxunit
MxunitMxunit
Mxunit
 
An introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduceAn introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduce
 
Intro to Testing in Zope, Plone
Intro to Testing in Zope, PloneIntro to Testing in Zope, Plone
Intro to Testing in Zope, Plone
 
Automated testing in Drupal
Automated testing in DrupalAutomated testing in Drupal
Automated testing in Drupal
 
Monitoring MySQL with DTrace/SystemTap
Monitoring MySQL with DTrace/SystemTapMonitoring MySQL with DTrace/SystemTap
Monitoring MySQL with DTrace/SystemTap
 
Appium TestNG Framework and Multi-Device Automation Execution
Appium TestNG Framework and Multi-Device Automation ExecutionAppium TestNG Framework and Multi-Device Automation Execution
Appium TestNG Framework and Multi-Device Automation Execution
 
Practical Glusto Example
Practical Glusto ExamplePractical Glusto Example
Practical Glusto Example
 
Drupal Modules
Drupal ModulesDrupal Modules
Drupal Modules
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
 
2 second lesson- attributes
2 second lesson- attributes2 second lesson- attributes
2 second lesson- attributes
 
Writing Plugged-in Java EE Apps: Jason Lee
Writing Plugged-in Java EE Apps: Jason LeeWriting Plugged-in Java EE Apps: Jason Lee
Writing Plugged-in Java EE Apps: Jason Lee
 
Mule ctf
Mule  ctfMule  ctf
Mule ctf
 
Using Twig with Drupal 7
Using Twig with Drupal 7Using Twig with Drupal 7
Using Twig with Drupal 7
 
Drupal Best Practices
Drupal Best PracticesDrupal Best Practices
Drupal Best Practices
 
Grails 1.1 Testing - Unit, Integration & Functional
Grails 1.1 Testing - Unit, Integration & FunctionalGrails 1.1 Testing - Unit, Integration & Functional
Grails 1.1 Testing - Unit, Integration & Functional
 
Automated php unit testing in drupal 8
Automated php unit testing in drupal 8Automated php unit testing in drupal 8
Automated php unit testing in drupal 8
 
Drupalcamp Simpletest
Drupalcamp SimpletestDrupalcamp Simpletest
Drupalcamp Simpletest
 
Testing In Drupal
Testing In DrupalTesting In Drupal
Testing In Drupal
 

Último

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Último (20)

08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 

Continuous Integration and Drupal

  • 1. CONTINUOUS INTEGRATION Automatically Install, Test, and Deploy Your Drupal Site Wednesday, December 16, 2009
  • 2. Testing and Drupal The focus of Drupal 7 has largely been on automated testing and Drupal adopted SimpleTest as its test framework of choice. Major Drupal 6 modules are starting to get unit tests, but their correctness varies. Regardless, it’s still easy to write your own unit tests. Wednesday, December 16, 2009
  • 3. SimpleTest SimpleTest is a testing framework that has been adopted for use in Drupal core and contrib. Drupal 7 core is automatically tested using the PIFR module and testing slaves. We’ll talk later about getting SimpleTests running automatically as part of our Hudson continuous integration framework. Wednesday, December 16, 2009
  • 4. Running Tests SimpleTest is a contributed module for Drupal 6. It is in Drupal 7 core, and it also happens to be part of the Pressflow distribution’s core set of modules. To run tests, the SimpleTest module must be enabled. (Our install profile turns it on by default.) Then you can head to / admin/build/testing to see all the available tests. Wednesday, December 16, 2009
  • 5. The SimpleTest Interface Each test shown in the SimpleTest administrative interface is an instance of the DrupalWebTestCase class. Each of these tests may contain multiple assertions. Wednesday, December 16, 2009
  • 6. Running Tests For each assertion in a test, SimpleTest will log whether each passed or failed, along with any PHP exceptions that happen along the way. Wednesday, December 16, 2009
  • 7. Testing Workflow Ideally, SimpleTests should all be run prior to a commit so that we’re not relying on Hudson to find errors in unit tests. As of right now, quite a few contributed modules have test failures. Wednesday, December 16, 2009
  • 8. Writing SimpleTests SimpleTest looks for .test files. They should be placed inside a tests folder in your module’s folder. (The modules for Drupal 7’s tests, and the backported block tests for Pressflow are located in the <htdocs>/modules/simpletest/tests.) Each .test file may contain one or more classes that extend DrupalWebTestCase. Wednesday, December 16, 2009
  • 9. DrupalWebTestCase The DrupalWebTestCase (hereafter DWTC) class defines a number of extra helper methods besides the ones provided by SimpleTest and also defines a Drupal-specific default setup and teardown behavior. You can find the definition for this class at drupal_web_test_case.php inside the simpletest folder. Wednesday, December 16, 2009
  • 10. Your Test Classes Each class that inherits from DWTC should provide an implementation of the DrupalWebTestCase::getInfo() method: function getInfo() { return array( 'name' => t('RSS and XML formatting tests'), 'description' => t('Tests for the format_rss_item() and format_xml_elements() functions.'), 'group' => t('System'), ); } This information shows up on the SimpleTest admin screen. Wednesday, December 16, 2009
  • 11. Your Tests In addition to getInfo(), you must create a least one testing method. SimpleTest will run any public methods whose names begin with “test”. Wednesday, December 16, 2009
  • 12. Behind the Scenes So how does SimpleTest work without disturbing your local database? The real magic happens in the DrupalWebTestCase::setUp() method. That method creates a new random numerical prefix and then uses Drupal’s database prefixing feature to install a new, empty copy of Drupal with the default install profile using the random database prefix. It also creates a temporary files directory (also prefixed with the random number) in the current files directory. Wednesday, December 16, 2009
  • 13. Behind The Scenes, Cont’d Although it doesn’t show it as a parameter, ::setUp() will also take a variable number of extra arguments as modules that should be enabled in addition to those that come with the default profile. Since block.module is enabled in the default install profile, for example, BlockTestCase doesn’t have to call setUp() with any extra arguments. However, CCK’s tests need to look in the database, and so they need at least the content and text CCK modules, and the schema module to examine DB schema. Wednesday, December 16, 2009
  • 14. Looking At Tests Here’s the BlockTestCase from block.test: class BlockTestCase extends DrupalWebTestCase { public static function getInfo() { return array( 'name' => t('Block functionality'), 'description' => t('Add, edit and delete custom block. Configure and move a module-defined block.'), 'group' => t('Block'), ); } Wednesday, December 16, 2009
  • 15. Looking At Tests Here’s the BlockTestCase from block.test: /** * Implementation of setUp(). */ function setUp() { parent::setUp(); // Create and login user $admin_user = $this->drupalCreateUser(array('administer blocks')); $this->drupalLogin($admin_user); } Wednesday, December 16, 2009
  • 16. Looking At Tests Compare that to the CCK ContentCrudTestCase, which is a base class that other CCK tests inherit from. Note how the setUp () method is set to enable the three modules the test will need. class ContentCrudTestCase extends DrupalWebTestCase { function setUp() { $args = func_get_args(); $modules = array_merge(array('content', 'schema', 'text'), $args); call_user_func_array(array('parent','setUp'), $modules); module_load_include('inc', 'content', 'includes/ content.crud'); Wednesday, December 16, 2009
  • 17. Basic Assertions The main assertions that are built into the UnitTestCase class (from which DrupalWebTestCase inherits) are documented at http://simpletest.org/api/SimpleTest/UnitTester/ UnitTestCase.html . Wednesday, December 16, 2009
  • 18. DrupalWebTestCase DrupalWebTestCase inherits from the SimpleTest library’s WebTestCase class, but also adds extra capabilities for accessing Drupal pages by URL, setting the logged in user, submitting forms with ::drupalPost() and more. You can read about these functions at http://drupal.org/node/ 265762 . Wednesday, December 16, 2009
  • 19. Test Types Sometimes you will want to create purely functional tests, as in one I wrote for D7 HEAD to test format_rss_item. This just tests the validity of a regular expression for several common possible XML tags. function testElementNameRegex() { $regex = '/^[w:][w-:]*$/'; $this->assertEqual(preg_match($regex, 'i<3badlyformattedtags'), 0, t('XML Element Regex is valid')); $this->assertEqual(preg_match($regex, 'georss:point'), 1, t('XML Element Regex is valid')); $this->assertEqual(preg_match($regex, ' not:valid'), 0, t('XML Element Regex is valid')); $this->assertEqual(preg_match($regex, '-not-so-valid'), 0, t('XML Element Regex is valid')); } Wednesday, December 16, 2009
  • 20. Test Types Most of your tests will involve using APIs, such as this test that tests the format_rss_item() call to make sure it escapes XSS. function testXSS() { $sanitized_title = check_plain($this->getRSSTitle()); $sanitized_link = check_url($this->getRSSLink()); $sanitized_description = check_plain($this->getRSSDescription()); $output = format_rss_item($this->getRSSTitle(), $this->getRSSLink(), $this->getRSSDescription(), array()); $simplexml_result = simplexml_load_string($output); Wednesday, December 16, 2009
  • 21. Test Types Most of your tests will involve using APIs, such as this test that tests the format_rss_item() call to make sure it escapes XSS. $this->assertTrue($simplexml_result !== FALSE, t('SimpleXML could properly parse the output')); $this->assertTrue(strpos($output, $sanitized_title) != FALSE, t('XSS attack %title was filtered', array('%title' => $this- >getRSSTitle()))); $this->assertTrue(strpos($output, $sanitized_link) != FALSE, t('Potentially dangerous URL %link was filtered to %sanitized_link', array('%link' => $this->getRSSLink(), '%sanitized_link' => $sanitized_link))); Wednesday, December 16, 2009
  • 22. Test-Driven Development A major focus of many agile development practices are Test- Driven (or Behavior-Driven) Development, whereby unit tests are written first to satisfy requirements, and can be continually tested as the project progresses. Another common thread in doing TDD is to bring tests into bug fixes. In many open-source projects, such as jQuery, people ask for a test case to demonstrate a bug, and then a new test can be written so that the regression never happens again. Wednesday, December 16, 2009
  • 23. Running Tests Can take a long time, especially if your install profile grows. Maybe we can enlist someone else to help out with them. Wednesday, December 16, 2009
  • 25. Installing Hudson Debian-based packages are available for Ubuntu http://hudson-ci.org/debian/ You can also run Hudson on Tomcat (beside a SOLR install, for example.) Hudson on Ubuntu installs your files at /var/lib/hudson/jobs/ [your job name]/workspace/[top-level SCM package] Wednesday, December 16, 2009
  • 26. Getting Hudson Working Set up source control Set up a build step that installs Drupal Set up a build step that runs SimpleTests via the shell script Set up JUnit reporting Profit? Wednesday, December 16, 2009
  • 27. Setting Up Source Control Put your SVN (or CVS or Mercurial, etc.) information into Hudson and save either credentials and/or a public/private keypair Set it up to automatically poll your repository for changes if you want automatic builds Wednesday, December 16, 2009
  • 28. Automatically Installing Make a vhost and a hosts entry for your Hudson checkout You’ll then want to make a shell script that: Runs drush provision to install your site Make sure your install profile installs SimpleTest! Wednesday, December 16, 2009
  • 29. Automatically Installing A sample script: #!/bin/bash SITE_PATH=/var/lib/hudson/jobs/ProvisionTest/workspace/trunk/ htdocs cd $SITE_PATH /bin/drush --root=$SITE_PATH --master_db_host=localhost -- master_db_user=root --db_type=mysql --db_host=localhost -- config_path=/etc/apache2/drush-conf --restart_cmd=echo -- uri=http://drushtest --script_user=hudson --profile=provision provision install drushtest Wednesday, December 16, 2009
  • 30. Running SimpleTests Your install profile must install SimpleTest so that you can use the run-tests.sh script to run a number of tests. ComputerMinds.co.uk started a SimpleTest patch to output test results in the JUnit XML format - this patch will be in Pressflow soon and is active on d.o: http://drupal.org/node/602332 Once you’re running this patch, your Hudson runs will keep track of the number of test passes and fails. Wednesday, December 16, 2009
  • 31. Running SimpleTests The other half of the same script, to handle automatically running SimpleTests: rm -rf scripts/tests/*.xml /usr/bin/php scripts/run-tests.sh --url http://drushtest --xml scripts/tests Provision Wednesday, December 16, 2009
  • 32. Hudson Results Build failure: when Drupal could not be installed, drush will return with an error, and Hudson will notify you that the build has failed. Common causes of this could be parse errors, modules that aren’t in source control but are referred to in the install profile, and so on. Unstable: the installation succeeded, but one or more unit tests did not complete successfully. Wednesday, December 16, 2009
  • 33. Hudson Results Success: Your installation succeeded and all unit tests passed! Wednesday, December 16, 2009
  • 34. Unit Testing Recipes Test your install profile! http://gist.github.com/249754 This code will let you make a unit test that installs your full install profile (in this case, called “provision”) and can then run tests against the fully-installed environment. Wednesday, December 16, 2009
  • 35. Gotchas Drush Provision isn’t _really_ meant to install one site many times. If your site’s URL is more than 14 characters, it will fail after the 10th install, since it makes a new database each time. All those databases will eventually slow your MySQL server down, so you manually have to remove them. Make sure that you install Provision for both the Hudson / Tomcat user and the main web user. Make sure you install curl, php-cli and php-curl so that SimpleTests can run from the command line. Wednesday, December 16, 2009