Daniel Kinzler has uploaded a new change for review.
https://gerrit.wikimedia.org/r/203809
Change subject: Isolate unit tests for wbsearchentities.
......................................................................
Isolate unit tests for wbsearchentities.
This implements DI for the SearchEntities class and migrates
the test case to use mock services.
Change-Id: Ia55f43c694470f481a26705d3216dc6a0c9de59a
---
M lib/tests/phpunit/store/MockTermIndex.php
M repo/includes/api/SearchEntities.php
M repo/tests/phpunit/includes/api/SearchEntitiesTest.php
3 files changed, 285 insertions(+), 43 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase
refs/changes/09/203809/1
diff --git a/lib/tests/phpunit/store/MockTermIndex.php
b/lib/tests/phpunit/store/MockTermIndex.php
index 42d386d..02826ca 100644
--- a/lib/tests/phpunit/store/MockTermIndex.php
+++ b/lib/tests/phpunit/store/MockTermIndex.php
@@ -291,21 +291,47 @@
if ( ( $language === null || $term->getLanguage() ===
$language )
&& ( $entityType === null ||
$term->getEntityType() === $entityType )
&& ( $termType === null || $term->getType() ===
$termType )
- && $this->termMatchesTemplates( $term, $terms )
+ && $this->termMatchesTemplates( $term, $terms,
$options )
) {
$matchingTerms[] = $term;
}
}
+ $limit = isset( $options['LIMIT'] ) ? $options['LIMIT'] : 0;
+
+ if ( $limit > 0 ) {
+ $matchingTerms = array_slice( $matchingTerms, 0, $limit
);
+ }
+
return $matchingTerms;
}
/**
- * @throws Exception always
+ * @param Term[] $terms
+ * @param null $entityType
+ * @param array $options
+ *
+ * @return \Wikibase\DataModel\Entity\EntityId[]
*/
public function getMatchingIDs( array $terms, $entityType = null, array
$options = array() ) {
- throw new Exception( 'not implemented by mock class ' );
+ $limit = isset( $options['LIMIT'] ) ? $options['LIMIT'] : 0;
+ unset( $options['LIMIT'] );
+
+ $terms = $this->getMatchingTerms( $terms, null, $entityType,
$options );
+
+ $ids = array();
+ foreach ( $terms as $term ) {
+ $id = $term->getEntityId();
+ $key = $id->getSerialization();
+ $ids[$key] = $id;
+ }
+
+ if ( $limit > 0 ) {
+ $ids = array_slice( $ids, 0, $limit );
+ }
+
+ return $ids;
}
/**
@@ -353,10 +379,11 @@
/**
* @param Term $term
* @param Term[] $templates
+ * @param array $options
*
* @return bool
*/
- private function termMatchesTemplates( Term $term, array $templates ) {
+ private function termMatchesTemplates( Term $term, array $templates,
array $options = array() ) {
foreach ( $templates as $template ) {
if ( $template->getType() !== null &&
$template->getType() != $term->getType() ) {
continue;
@@ -370,7 +397,7 @@
continue;
}
- if ( $template->getText() !== null &&
$template->getText() != $term->getText() ) {
+ if ( $template->getText() !== null &&
!$this->textMatches( $template->getText(), $term->getText(), $options ) ) {
continue;
}
@@ -384,4 +411,17 @@
return false;
}
+ private function textMatches( $find, $text, array $options = array() ) {
+
+ if ( isset( $options[ 'caseSensitive' ] ) && !$options[
'caseSensitive' ] ) {
+ $find = strtolower( $find );
+ $text = strtolower( $text );
+ }
+
+ if ( isset( $options[ 'prefixSearch' ] ) && $options[
'prefixSearch' ] ) {
+ $text = substr( $text, 0, strlen( $find ) );
+ }
+
+ return $find === $text;
+ }
}
diff --git a/repo/includes/api/SearchEntities.php
b/repo/includes/api/SearchEntities.php
index b774947..1dedced 100644
--- a/repo/includes/api/SearchEntities.php
+++ b/repo/includes/api/SearchEntities.php
@@ -7,9 +7,11 @@
use Wikibase\DataModel\Entity\EntityId;
use Wikibase\DataModel\Entity\EntityIdParser;
use Wikibase\DataModel\Entity\EntityIdParsingException;
+use Wikibase\Lib\ContentLanguages;
use Wikibase\Lib\Store\EntityTitleLookup;
use Wikibase\Repo\WikibaseRepo;
use Wikibase\Term;
+use Wikibase\TermIndex;
/**
* API module to search for Wikibase entities.
@@ -42,6 +44,21 @@
private $idParser;
/**
+ * @var TermIndex
+ */
+ private $termIndex;
+
+ /**
+ * @var ContentLanguages
+ */
+ private $termsLanguages;
+
+ /**
+ * @var string[]
+ */
+ private $entityTypes;
+
+ /**
* @param ApiMain $mainModule
* @param string $moduleName
* @param string $modulePrefix
@@ -51,9 +68,37 @@
public function __construct( ApiMain $mainModule, $moduleName,
$modulePrefix = '' ) {
parent::__construct( $mainModule, $moduleName, $modulePrefix );
- //TODO: provide a mechanism to override the services
- $this->titleLookup =
WikibaseRepo::getDefaultInstance()->getEntityTitleLookup();
- $this->idParser =
WikibaseRepo::getDefaultInstance()->getEntityIdParser();
+ $repo = WikibaseRepo::getDefaultInstance();
+ $this->setServices(
+ $repo->getStore()->getTermIndex(),
+ $repo->getEntityTitleLookup(),
+ $repo->getEntityIdParser(),
+ $repo->getEntityFactory()->getEntityTypes(),
+ $repo->getTermsLanguages()
+ );
+ }
+
+ /**
+ * Override services, for use for testing.
+ *
+ * @param TermIndex $termIndex
+ * @param EntityTitleLookup $titleLookup
+ * @param EntityIdParser $idParser
+ * @param array $entityTypes
+ * @param ContentLanguages $termLanguages
+ */
+ public function setServices(
+ TermIndex $termIndex,
+ EntityTitleLookup $titleLookup,
+ EntityIdParser $idParser,
+ array $entityTypes,
+ ContentLanguages $termLanguages
+ ) {
+ $this->termIndex = $termIndex;
+ $this->titleLookup = $titleLookup;
+ $this->idParser = $idParser;
+ $this->entityTypes = $entityTypes;
+ $this->termsLanguages = $termLanguages;
}
/**
@@ -69,17 +114,17 @@
* @return EntityId[]
*/
private function searchEntities( $term, $entityType, $language, $limit,
$prefixSearch ) {
- return
WikibaseRepo::getDefaultInstance()->getStore()->getTermIndex()->getMatchingIDs(
+ return $this->termIndex->getMatchingIDs(
array(
new Term( array(
- 'termType' =>
Term::TYPE_LABEL,
- 'termLanguage' => $language,
- 'termText' => $term
+ 'termType' => Term::TYPE_LABEL,
+ 'termLanguage' => $language,
+ 'termText' => $term
) ),
new Term( array(
- 'termType' =>
Term::TYPE_ALIAS,
- 'termLanguage' => $language,
- 'termText' => $term
+ 'termType' => Term::TYPE_ALIAS,
+ 'termLanguage' => $language,
+ 'termText' => $term
) )
),
$entityType,
@@ -204,7 +249,7 @@
}
// Find all the remaining terms for the given entities
- $terms =
WikibaseRepo::getDefaultInstance()->getStore()->getTermIndex()->getTermsOfEntities(
+ $terms = $this->termIndex->getTermsOfEntities(
$entityIds, null, array( $languageCode ) );
// TODO: This needs to be rethought when a different search
engine is used
$aliasPattern = '/^' . preg_quote( $search, '/' ) . '/i';
@@ -305,7 +350,6 @@
* @see ApiBase::getAllowedParams
*/
protected function getAllowedParams() {
- $entityFactory =
WikibaseRepo::getDefaultInstance()->getEntityFactory();
return array(
'search' => array(
@@ -313,11 +357,11 @@
ApiBase::PARAM_REQUIRED => true,
),
'language' => array(
- ApiBase::PARAM_TYPE =>
WikibaseRepo::getDefaultInstance()->getTermsLanguages()->getLanguages(),
+ ApiBase::PARAM_TYPE =>
$this->termsLanguages->getLanguages(),
ApiBase::PARAM_REQUIRED => true,
),
'type' => array(
- ApiBase::PARAM_TYPE =>
$entityFactory->getEntityTypes(),
+ ApiBase::PARAM_TYPE => $this->entityTypes,
ApiBase::PARAM_DFLT => 'item',
),
'limit' => array(
diff --git a/repo/tests/phpunit/includes/api/SearchEntitiesTest.php
b/repo/tests/phpunit/includes/api/SearchEntitiesTest.php
index 46811de..b35f3e7 100644
--- a/repo/tests/phpunit/includes/api/SearchEntitiesTest.php
+++ b/repo/tests/phpunit/includes/api/SearchEntitiesTest.php
@@ -2,11 +2,23 @@
namespace Wikibase\Test\Api;
+use ApiMain;
+use FauxRequest;
+use RequestContext;
+use Title;
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\Lib\ContentLanguages;
+use Wikibase\Lib\Store\EntityTitleLookup;
+use Wikibase\Term;
+use Wikibase\TermIndex;
+use Wikibase\Api\SearchEntities;
+use Wikibase\DataModel\Entity\BasicEntityIdParser;
+use Wikibase\Test\MockTermIndex;
+
/**
* @covers Wikibase\Api\SearchEntities
*
* @group API
- * @group Database
* @group Wikibase
* @group WikibaseAPI
* @group WikibaseRepo
@@ -15,20 +27,167 @@
*
* @licence GNU GPL v2+
* @author Adam Shorland
+ * @author Daniel Kinzler
*/
-class SearchEntitiesTest extends WikibaseApiTestCase {
+class SearchEntitiesTest extends \PHPUnit_Framework_TestCase {
- private static $hasSetup;
+ private static $terms = array(
+ 'Berlin' => array(
+ "id" => 'Q64',
+ "labels" => array(
+ array( "language" => "en", "value" => "Berlin"
),
+ array( "language" => "de", "value" => "Berlin"
),
+ ),
+ "aliases" => array(
+ array( array( "language" => "de", "value" =>
"Dickes B" ) ),
+ array( array( "language" => "en", "value" =>
"Dickes B" ) ),
+ ),
+ "descriptions" => array(
+ array( "language" => "en", "value" => "Capital
city and a federated state of the Federal Republic of Germany." ),
+ array( "language" => "de", "value" =>
"Bundeshauptstadt und Regierungssitz der Bundesrepublik Deutschland." ),
+ ),
+ ),
+ 'Bern' => array(
+ "id" => "Q45",
+ "labels" => array(
+ array( "language" => "en", "value" => "Bern" ),
+ array( "language" => "de", "value" => "Bern" ),
+ array( "language" => "fr", "value" => "Berne" ),
+ array( "language" => "it", "value" => "Berna" ),
+ ),
+ "aliases" => array(
+ ),
+ "descriptions" => array(
+ array( "language" => "de", "value" => "Stadt in
der Schweiz." ),
+ ),
+ ),
+ 'Guangzhou' => array(
+ "id" => "Q231",
+ "labels" => array(
+ array( "language" => "en", "value" =>
"Guangzhou" ),
+ array( "language" => "yue", "value" => "廣州" ),
+ array( "language" => "zh-cn", "value" => "广州市"
),
+ ),
+ "aliases" => array(
+ ),
+ "descriptions" => array(
+ array( "language" => "en", "value" => "Capital
of Guangdong." ),
+ array( "language" => "zh-hk", "value" =>
"廣東的省會。" ),
+ ),
+ ),
+ );
- protected function setUp() {
- parent::setUp();
+ private function getEntityId( $handle ) {
+ $parser = new BasicEntityIdParser();
+ return $parser->parse( self::$terms[$handle]['id'] );
+ }
- if( !isset( self::$hasSetup ) ) {
- $this->initTestEntities( array( 'StringProp', 'Berlin',
'London', 'Oslo', 'Episkopi',
- 'Leipzig', 'Guangzhou', 'Osaka' )
- );
+ private function getEntityData( $handle ) {
+ return self::$terms[$handle];
+ }
+
+ /**
+ * @param array $params
+ *
+ * @return ApiMain
+ */
+ private function getApiMain( array $params ) {
+ $context = new RequestContext();
+ $context->setRequest( new FauxRequest( $params, true ) );
+
+ $main = new ApiMain( $context );
+ return $main;
+ }
+
+ /**
+ * @return EntityTitleLookup
+ */
+ private function getTitleLookup() {
+ $titleLookup = $this->getMock(
'Wikibase\Lib\Store\EntityTitleLookup' );
+ $titleLookup->expects( $this->any() )->method( 'getTitleForId' )
+ ->will( $this->returnCallback( function( EntityId $id )
{
+ $title = Title::makeTitle( NS_MAIN,
$id->getEntityType() . ':' . $id->getSerialization() );
+ $title->resetArticleID( $id->getNumericId() );
+ return $title;
+ } ) );
+
+ return $titleLookup;
+ }
+
+ /**
+ * @return ContentLanguages
+ */
+ private function getContentLanguages() {
+ $titleLookup = $this->getMock( 'Wikibase\Lib\ContentLanguages'
);
+ $titleLookup->expects( $this->any() )->method( 'getLanguages' )
+ ->will( $this->returnValue( array( 'de', 'de-ch', 'en',
'ii', 'nn', 'ru', 'zh-cn' ) ) );
+
+ return $titleLookup;
+ }
+
+ /**
+ * @return TermIndex
+ */
+ private function getTermIndex() {
+ $idParser = new BasicEntityIdParser();
+ $termObjects = array();
+ foreach ( self::$terms as $entity ) {
+ $id = $idParser->parse( $entity['id'] );
+
+ foreach ( $entity['labels'] as $row ) {
+ $termObjects[] = $this->newTermFromDataRow(
$id, Term::TYPE_LABEL, $row );
+ }
+
+ foreach ( $entity['descriptions'] as $row ) {
+ $termObjects[] = $this->newTermFromDataRow(
$id, Term::TYPE_DESCRIPTION, $row );
+ }
+
+ foreach ( $entity['aliases'] as $rows ) {
+ foreach ( $rows as $row ) {
+ $termObjects[] =
$this->newTermFromDataRow( $id, Term::TYPE_ALIAS, $row );
+ }
+ }
}
- self::$hasSetup = true;
+
+ $termIndex = new MockTermIndex( $termObjects );
+
+ return $termIndex;
+ }
+
+ private function newTermFromDataRow( EntityId $entityId, $type, $row ) {
+ return new Term( array(
+ 'termType' => $type,
+ 'termLanguage' => $row['language'],
+ 'termText' => $row['value'],
+ 'entityType' => $entityId->getEntityType(),
+ 'entityId' => $entityId->getNumericId()
+ ) );
+ }
+
+ /**
+ * @param array $params
+ *
+ * @return array[]
+ */
+ private function callApiModule( array $params ) {
+ $module = new SearchEntities(
+ $this->getApiMain( $params ),
+ 'wbsearchentities'
+ );
+
+ $module->setServices(
+ $this->getTermIndex(),
+ $this->getTitleLookup(),
+ new BasicEntityIdParser(),
+ array( 'item', 'property' ),
+ $this->getContentLanguages()
+
+ );
+
+ $module->execute();
+
+ $result = $module->getResult();
+ return $result->getData();
}
public function provideData() {
@@ -36,14 +195,13 @@
//Search via full Labels
$testCases[] = array( array( 'search' => 'berlin', 'language'
=> 'en' ), array( 'handle' => 'Berlin' ) );
- $testCases[] = array( array( 'search' => 'LoNdOn', 'language'
=> 'en' ), array( 'handle' => 'London' ) );
- $testCases[] = array( array( 'search' => 'OSLO', 'language' =>
'en' ), array( 'handle' => 'Oslo' ) );
+ $testCases[] = array( array( 'search' => 'bERliN', 'language'
=> 'en' ), array( 'handle' => 'Berlin' ) );
+ $testCases[] = array( array( 'search' => 'BERLIN', 'language'
=> 'en' ), array( 'handle' => 'Berlin' ) );
$testCases[] = array( array( 'search' => '广州市', 'language' =>
'zh-cn' ), array( 'handle' => 'Guangzhou' ) );
//Search via partial Labels
- $testCases[] = array( array( 'search' => 'BER', 'language' =>
'nn' ), array( 'handle' => 'Berlin' ) );
- $testCases[] = array( array( 'search' => 'Episkop', 'language'
=> 'de' ), array( 'handle' => 'Episkopi' ) );
- $testCases[] = array( array( 'search' => 'L', 'language' =>
'de' ), array( 'handle' => 'Leipzig' ) );
+ $testCases[] = array( array( 'search' => 'BER', 'language' =>
'de' ), array( 'handle' => 'Berlin' ) );
+ $testCases[] = array( array( 'search' => '广', 'language' =>
'zh-cn' ), array( 'handle' => 'Guangzhou' ) );
return $testCases;
}
@@ -54,7 +212,7 @@
public function testSearchEntities( $params, $expected ) {
$params['action'] = 'wbsearchentities';
- list( $result,, ) = $this->doApiRequest( $params );
+ $result = $this->callApiModule( $params );
$this->assertResultLooksGood( $result );
$this->assertApiResultHasExpected( $result['search'], $params,
$expected );
@@ -63,31 +221,30 @@
public function testSearchExactMatch() {
$params = array(
'action' => 'wbsearchentities',
- 'search' => EntityTestHelper::getId( 'Berlin' ),
+ 'search' => $this->getEntityId( 'Berlin' ),
'language' => 'en'
);
$expected = array( 'handle' => 'Berlin' );
- list( $result,, ) = $this->doApiRequest( $params );
+ $result = $this->callApiModule( $params );
$this->assertApiResultHasExpected( $result['search'], $params,
$expected );
}
public function testSearchContinue() {
$params = array(
'action' => 'wbsearchentities',
- 'search' => 'O',
- 'language' => 'en',
+ 'search' => 'B',
+ 'language' => 'de',
'limit' => 1
);
- list( $result,, ) = $this->doApiRequest( $params );
+ $result = $this->callApiModule( $params );
$this->assertArrayHasKey( 'search-continue', $result );
}
private function assertResultLooksGood( $result ) {
- $this->assertResultSuccess( $result );
$this->assertArrayHasKey( 'searchinfo', $result );
$this->assertArrayHasKey( 'search', $result['searchinfo'] );
$this->assertArrayHasKey( 'search', $result );
@@ -103,8 +260,8 @@
private function assertApiResultHasExpected( $searchResults, $params,
$expected ) {
$foundResult = 0;
- $expectedId = EntityTestHelper::getId( $expected['handle'] );
- $expectedData = EntityTestHelper::getEntityData(
$expected['handle'] );
+ $expectedId = $this->getEntityId( $expected['handle']
)->getSerialization();
+ $expectedData = $this->getEntityData( $expected['handle'] );
foreach( $searchResults as $searchResult ) {
$assertFound = $this->assertSearchResultHasExpected(
$searchResult, $params, $expectedId, $expectedData );
@@ -145,4 +302,5 @@
}
}
}
+
}
--
To view, visit https://gerrit.wikimedia.org/r/203809
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia55f43c694470f481a26705d3216dc6a0c9de59a
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits