http://www.mediawiki.org/wiki/Special:Code/MediaWiki/82867
Revision: 82867
Author: platonides
Date: 2011-02-26 21:49:42 +0000 (Sat, 26 Feb 2011)
Log Message:
-----------
Finally commit the testing stuff I have been with this week. Could be
considered a continuation of r79411.
Mixture of the NewParserTests.php with old code present in
MediaWikiParserTest.php, reverting r79184 (revert of a revert...) and even
eval().
Using the iterator as dataProvider, but defering the insertion of articles, as
the dataprovider is processed on load, before switching dbs.
Each parser test appear now as a phpunit test. This means that by adding 683
tests (partly from extensions) we now surpass two thousand tests.
The downside of that is that they become painfully slow.
Initialise $wgHooks to $wgHooks, not to array() (r82499) as otherwise we lose
ParserFirstCallInit registrations.
There's no attempt to support extensions registering to $wgParser instead of
using ParserFirstCallInit properly (Cite falls in this category).
Modified Paths:
--------------
trunk/phase3/tests/phpunit/MediaWikiTestCase.php
trunk/phase3/tests/phpunit/includes/parser/MediaWikiParserTest.php
trunk/phase3/tests/phpunit/includes/parser/NewParserHelpers.php
trunk/phase3/tests/phpunit/includes/parser/NewParserTest.php
Modified: trunk/phase3/tests/phpunit/MediaWikiTestCase.php
===================================================================
--- trunk/phase3/tests/phpunit/MediaWikiTestCase.php 2011-02-26 21:12:01 UTC
(rev 82866)
+++ trunk/phase3/tests/phpunit/MediaWikiTestCase.php 2011-02-26 21:49:42 UTC
(rev 82867)
@@ -30,7 +30,13 @@
}
function run( PHPUnit_Framework_TestResult $result = NULL ) {
-
+ global $wgCaches;
+ /* Some functions require some kind of caching, and will end up
using the db,
+ * which we can't allow, as that would open a new connection
for mysql.
+ * Replace with a HashBag. They would not be going to persist
anyway.
+ */
+ $wgCaches[CACHE_DB] = new HashBagOStuff;
+
if( $this->needsDB() ) {
global $wgDBprefix;
Modified: trunk/phase3/tests/phpunit/includes/parser/MediaWikiParserTest.php
===================================================================
--- trunk/phase3/tests/phpunit/includes/parser/MediaWikiParserTest.php
2011-02-26 21:12:01 UTC (rev 82866)
+++ trunk/phase3/tests/phpunit/includes/parser/MediaWikiParserTest.php
2011-02-26 21:49:42 UTC (rev 82867)
@@ -1,66 +1,35 @@
<?php
require_once( dirname( __FILE__ ) . '/ParserHelpers.php' );
+require_once( dirname( __FILE__ ) . '/NewParserTest.php' );
require_once( dirname(dirname(dirname( __FILE__ ))) . '/bootstrap.php' );
/**
+ * The UnitTest must be either a class that inherits from
PHPUnit_Framework_TestCase
+ * or a class that provides a public static suite() method which returns
+ * an PHPUnit_Framework_Test object
+ *
* @group Parser
- * @group Destructive
* @group Database
- * @group Broken
- * It's not really broken, but superseded
*/
-class MediaWikiParserTest extends MediaWikiTestCase {
- public $count; // Number of tests in the suite.
- public $articles = array(); // Array of test articles defined by
the tests
- protected $pt;
-
- function setUp() {
- global $wgContLang;
- $wgContLang = Language::factory( 'en' );
-
- $this->pt = new PHPUnitParserTest;
- $this->pt->setupDatabase();
-
- }
-
- function tearDown() {
- if( is_object( $this->pt ) && $this->pt instanceof
PHPUnitParserTest ) {
- $this->pt->teardownDatabase();
- $this->pt = null;
- }
- }
+class MediaWikiParserTest {
-
- public function testParserTests() {
- //global $IP;
- //$wgParserTestFiles = array(
"$IP/tests/parser/testparserTests.txt" );
-
- global $wgParserTestFiles;
-
- foreach( $wgParserTestFiles as $file ) {
+ public static function suite() {
+ global $IP, $wgParserTestFiles;
+
+ $suite = new PHPUnit_Framework_TestSuite;
+
+ foreach ( $wgParserTestFiles as $filename ) {
+ $testsName = basename( $filename, '.txt' );
+ $className = /*ucfirst( basename( dirname( $filename )
) ) .*/ ucfirst( basename( $filename, '.txt' ) );
- $iter = new TestFileIterator( $file, $this->pt );
-
- try {
- foreach( $iter as $test ) {
- $r = $this->pt->runTest( $test['test'],
$test['input'],
- $test['result'],
$test['options'], $test['config']
- );
-
- $this->assertTrue( $r, 'Parser test ' .
$test['test'] );
-
- }
- }
- catch( DBQueryError $e ) {
- $this->assertTrue( false, 'Parser test ' .
$test['test'] . ' (error: "' . $e->getMessage() . '")' );
- //This is annoying... it always stops on error
and doesn't go to the next one.
- continue;
- }
-
+ eval( "/** @group Database\n@group Parser\n*/ class
$className extends NewParserTest { protected \$file = \"" . addslashes(
$filename ) . "\"; } " );
+
+ $parserTester = new $className( $testsName );
+ $suite->addTestSuite( new ReflectionClass (
$parserTester ) );
}
- }
+ return $suite;
+ }
}
-
Modified: trunk/phase3/tests/phpunit/includes/parser/NewParserHelpers.php
===================================================================
--- trunk/phase3/tests/phpunit/includes/parser/NewParserHelpers.php
2011-02-26 21:12:01 UTC (rev 82866)
+++ trunk/phase3/tests/phpunit/includes/parser/NewParserHelpers.php
2011-02-26 21:49:42 UTC (rev 82867)
@@ -169,11 +169,11 @@
}
$this->test = array(
- 'test' =>
$this->parserTest->removeEndingNewline( $data['test'] ),
- 'input' =>
$this->parserTest->removeEndingNewline( $data['input'] ),
- 'result' =>
$this->parserTest->removeEndingNewline( $data['result'] ),
- 'options' =>
$this->parserTest->removeEndingNewline( $data['options'] ),
- 'config' =>
$this->parserTest->removeEndingNewline( $data['config'] ) );
+
$this->parserTest->removeEndingNewline( $data['test'] ),
+
$this->parserTest->removeEndingNewline( $data['input'] ),
+
$this->parserTest->removeEndingNewline( $data['result'] ),
+
$this->parserTest->removeEndingNewline( $data['options'] ),
+
$this->parserTest->removeEndingNewline( $data['config'] ) );
return true;
}
Modified: trunk/phase3/tests/phpunit/includes/parser/NewParserTest.php
===================================================================
--- trunk/phase3/tests/phpunit/includes/parser/NewParserTest.php
2011-02-26 21:12:01 UTC (rev 82866)
+++ trunk/phase3/tests/phpunit/includes/parser/NewParserTest.php
2011-02-26 21:49:42 UTC (rev 82867)
@@ -2,9 +2,16 @@
/**
* @group Database
+ * @group Parser
+ * @group Stub (can also work independently)
*/
class NewParserTest extends MediaWikiTestCase {
+ static protected $articles = array(); // Array of test articles
defined by the tests
+ /* The dataProvider is run on a different instance than the test, so it
must be static
+ * When running tests from several files, all tests will see all
articles.
+ */
+
public $uploadDir;
public $keepUploads = false;
public $runDisabled = false;
@@ -21,10 +28,15 @@
public $fuzzSeed = 0;
public $memoryLimit = 50;
- //PHPUnit + MediaWikiTestCase functions
-
+ protected $file = false;
+
+ /*function __construct($a = null,$b = array(),$c = null ) {
+ parent::__construct($a,$b,$c);
+ }*/
+
function setUp() {
- global $wgContLang, $wgNamespaceProtection,
$wgNamespaceAliases, $IP;
+ global $wgContLang, $wgNamespaceProtection, $wgNamespaceAliases;
+ global $wgHooks, $IP;
$wgContLang = Language::factory( 'en' );
//Setup CLI arguments
@@ -56,7 +68,7 @@
);
$tmpGlobals['wgEnableParserCache'] = false;
- $tmpGlobals['wgHooks'] = array();
+ $tmpGlobals['wgHooks'] = $wgHooks;
$tmpGlobals['wgDeferredUpdateList'] = array();
$tmpGlobals['wgMemc'] = &wfGetMainCache();
$tmpGlobals['messageMemc'] = &wfGetMessageCacheStorage();
@@ -152,8 +164,9 @@
MessageCache::singleton()->clear();
$this->uploadDir = $this->setupUploadDir();
-
+
$user = User::newFromId( 0 );
+ LinkCache::singleton()->clear(); # Avoids the odd failure at
creating the nullRevision
$image = wfLocalFile( Title::makeTitle( NS_FILE, 'Foobar.jpg' )
);
$image->recordUpload2( '', 'Upload of some lame file', 'Some
lame file', array(
@@ -258,7 +271,8 @@
'wgHtml5' => true,
'wgWellFormedXml' => true,
'wgAllowMicrodataAttributes' => true,
- 'wgAdaptiveMessageCache' => true
+ 'wgAdaptiveMessageCache' => true,
+ 'wgUseDatabaseMessages' => true,
);
if ( $config ) {
@@ -295,6 +309,13 @@
MagicWord::clearCache();
+ # Publish the articles after we have the final language set
+ $this->publishTestArticles();
+
+ # The entries saved into RepoGroup cache with previous globals
will be wrong.
+ RepoGroup::destroySingleton();
+ MessageCache::singleton()->destroyInstance();
+
global $wgUser;
$wgUser = new User();
}
@@ -345,115 +366,93 @@
return $dir;
}
+ public function parserTestProvider() {
+ if ( $this->file === false ) {
+ global $wgParserTestFiles;
+ $this->file = $wgParserTestFiles[0];
+ }
+ return new ParserTestFileIterator( $this->file, $this );
+ }
+ /**
+ * Set the file from whose tests will be run by this instance
+ */
+ public function setParserTestFile( $filename ) {
+ $this->file = $filename;
+ }
-
-
- //Actual test suites
+ /** @dataProvider parserTestProvider */
+ public function testParserTest( $desc, $input, $result, $opts, $config
) {
+ if ( !preg_match( '/' . $this->regex . '/', $desc ) ) return;
//$this->markTestSkipped( 'Filtered out by the user' );
+ $opts = $this->parseOptions( $opts );
+ $this->setupGlobals( $opts, $config );
- public function testParserTests() {
-
- global $wgParserTestFiles;
-
- $files = $wgParserTestFiles;
-
- if( $this->getCliArg( 'file=' ) ) {
- $files = array( $this->getCliArg( 'file=' ) );
+ $user = new User();
+ $options = ParserOptions::newFromUser( $user );
+
+ if ( isset( $opts['title'] ) ) {
+ $titleText = $opts['title'];
}
+ else {
+ $titleText = 'Parser test';
+ }
+
+ $local = isset( $opts['local'] );
+ $preprocessor = isset( $opts['preprocessor'] ) ?
$opts['preprocessor'] : null;
+ $parser = $this->getParser( $preprocessor );
- foreach( $files as $file ) {
-
- $iter = new ParserTestFileIterator( $file, $this );
-
- foreach ( $iter as $t ) {
-
- try {
-
- $desc = $t['test'];
- $input = $t['input'];
- $result = $t['result'];
- $opts = $t['options'];
- $config = $t['config'];
-
-
- $opts = $this->parseOptions( $opts );
- $this->setupGlobals( $opts, $config );
-
- $user = new User();
- $options = ParserOptions::newFromUser(
$user );
-
- if ( isset( $opts['title'] ) ) {
- $titleText = $opts['title'];
- }
- else {
- $titleText = 'Parser test';
- }
-
- $local = isset( $opts['local'] );
- $preprocessor = isset(
$opts['preprocessor'] ) ? $opts['preprocessor'] : null;
- $parser = $this->getParser(
$preprocessor );
- $title = Title::newFromText( $titleText
);
-
- if ( isset( $opts['pst'] ) ) {
- $out =
$parser->preSaveTransform( $input, $title, $user, $options );
- } elseif ( isset( $opts['msg'] ) ) {
- $out = $parser->transformMsg(
$input, $options );
- } elseif ( isset( $opts['section'] ) ) {
- $section = $opts['section'];
- $out = $parser->getSection(
$input, $section );
- } elseif ( isset( $opts['replace'] ) ) {
- $section = $opts['replace'][0];
- $replace = $opts['replace'][1];
- $out = $parser->replaceSection(
$input, $section, $replace );
- } elseif ( isset( $opts['comment'] ) ) {
- $linker = $user->getSkin();
- $out = $linker->formatComment(
$input, $title, $local );
- } elseif ( isset( $opts['preload'] ) ) {
- $out = $parser->getpreloadText(
$input, $title, $options );
- } else {
- $output = $parser->parse(
$input, $title, $options, true, true, 1337 );
- $out = $output->getText();
-
- if ( isset( $opts['showtitle']
) ) {
- if (
$output->getTitleText() ) {
- $title =
$output->getTitleText();
- }
-
- $out = "$title\n$out";
- }
-
- if ( isset( $opts['ill'] ) ) {
- $out = $this->tidy(
implode( ' ', $output->getLanguageLinks() ) );
- } elseif ( isset( $opts['cat']
) ) {
- global $wgOut;
-
-
$wgOut->addCategoryLinks( $output->getCategories() );
- $cats =
$wgOut->getCategoryLinks();
-
- if ( isset(
$cats['normal'] ) ) {
- $out =
$this->tidy( implode( ' ', $cats['normal'] ) );
- } else {
- $out = '';
- }
- }
- $parser->mPreprocessor = null;
-
- $result = $this->tidy( $result
);
- }
-
- $this->teardownGlobals();
-
- $this->assertEquals( $result, $out,
$desc );
-
+ $title = Title::newFromText( $titleText );
+
+ if ( isset( $opts['pst'] ) ) {
+ $out = $parser->preSaveTransform( $input, $title,
$user, $options );
+ } elseif ( isset( $opts['msg'] ) ) {
+ $out = $parser->transformMsg( $input, $options );
+ } elseif ( isset( $opts['section'] ) ) {
+ $section = $opts['section'];
+ $out = $parser->getSection( $input, $section );
+ } elseif ( isset( $opts['replace'] ) ) {
+ $section = $opts['replace'][0];
+ $replace = $opts['replace'][1];
+ $out = $parser->replaceSection( $input, $section,
$replace );
+ } elseif ( isset( $opts['comment'] ) ) {
+ $linker = $user->getSkin();
+ $out = $linker->formatComment( $input, $title, $local );
+ } elseif ( isset( $opts['preload'] ) ) {
+ $out = $parser->getpreloadText( $input, $title,
$options );
+ } else {
+ $output = $parser->parse( $input, $title, $options,
true, true, 1337 );
+ $out = $output->getText();
+
+ if ( isset( $opts['showtitle'] ) ) {
+ if ( $output->getTitleText() ) {
+ $title = $output->getTitleText();
}
- catch( Exception $e ) {
- $this->assertTrue( false, $t['test'] .
' (failed: ' . $e->getMessage() . ')' );
+
+ $out = "$title\n$out";
+ }
+
+ if ( isset( $opts['ill'] ) ) {
+ $out = $this->tidy( implode( ' ',
$output->getLanguageLinks() ) );
+ } elseif ( isset( $opts['cat'] ) ) {
+ global $wgOut;
+
+ $wgOut->addCategoryLinks(
$output->getCategories() );
+ $cats = $wgOut->getCategoryLinks();
+
+ if ( isset( $cats['normal'] ) ) {
+ $out = $this->tidy( implode( ' ',
$cats['normal'] ) );
+ } else {
+ $out = '';
}
-
}
-
+ $parser->mPreprocessor = null;
+
+ $result = $this->tidy( $result );
}
-
+
+ $this->teardownGlobals();
+
+ $this->assertEquals( $result, $out, $desc );
}
/**
@@ -593,59 +592,34 @@
* Get a Parser object
*/
function getParser( $preprocessor = null ) {
- global $wgParserConf;
+ global $wgParserConf, $wgHooks;
$class = $wgParserConf['class'];
$parser = new $class( array( 'preprocessorClass' =>
$preprocessor ) + $wgParserConf );
- foreach ( $this->hooks as $tag => $callback ) {
- $parser->setHook( $tag, $callback );
- }
-
- foreach ( $this->functionHooks as $tag => $bits ) {
- list( $callback, $flags ) = $bits;
- $parser->setFunctionHook( $tag, $callback, $flags );
- }
-
wfRunHooks( 'ParserTestParser', array( &$parser ) );
return $parser;
}
//Various action functions
-
- /**
- * Insert a temporary test article
- * @param $name String: the title, including any prefix
- * @param $text String: the article text
- * @param $line Integer: the input line number, for reporting errors
- */
- public function addArticle( $name, $text, $line = 'unknown' ) {
- global $wgCapitalLinks;
- $text = $this->removeEndingNewline($text);
-
- $oldCapitalLinks = $wgCapitalLinks;
- $wgCapitalLinks = true; // We only need this from
SetupGlobals() See r70917#c8637
-
- $name = $this->removeEndingNewline( $name );
- $title = Title::newFromText( $name );
-
- if ( is_null( $title ) ) {
- throw new MWException( "invalid title ('$name' =>
'$title') at line $line\n" );
+ public function addArticle( $name, $text, $line ) {
+ self::$articles[$name] = $text;
+ }
+
+ public function publishTestArticles() {
+ if ( empty( self::$articles ) ) {
+ return;
}
- $aid = $title->getArticleID( Title::GAID_FOR_UPDATE );
+ foreach ( self::$articles as $name => $text ) {
+ $title = Title::newFromText( $name );
- if ( $aid != 0 ) {
- debug_print_backtrace();
- throw new MWException( "duplicate article '$name' at
line $line\n" );
+ if ( $title->getArticleID( Title::GAID_FOR_UPDATE ) ==
0 ) {
+ ParserTest::addArticle( $name, $text );
+ }
}
-
- $art = new Article( $title );
- $art->doEdit( $text, '', EDIT_NEW );
-
- $wgCapitalLinks = $oldCapitalLinks;
}
/**
@@ -658,19 +632,15 @@
*/
public function requireHook( $name ) {
global $wgParser;
-
$wgParser->firstCallInit( ); // make sure hooks are loaded.
-
- if ( isset( $wgParser->mTagHooks[$name] ) ) {
- $this->hooks[$name] = $wgParser->mTagHooks[$name];
- } else {
- echo " This test suite requires the '$name' hook
extension, skipping.\n";
- return false;
- }
-
- return true;
+ return isset( $wgParser->mTagHooks[$name] );
}
+ public function requireFunctionHook( $name ) {
+ global $wgParser;
+ $wgParser->firstCallInit( ); // make sure hooks are loaded.
+ return isset( $wgParser->mFunctionHooks[$name] );
+ }
//Various "cleanup" functions
/*
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs