Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to setup a Property for a PHP Unit Test #1340

Closed
WolfgangFahl opened this issue Jan 1, 2016 · 2 comments
Closed

How to setup a Property for a PHP Unit Test #1340

WolfgangFahl opened this issue Jan 1, 2016 · 2 comments
Labels

Comments

@WolfgangFahl
Copy link
Contributor

While working on https://www.semantic-mediawiki.org/wiki/User:WolfgangFahl/Workdocumentation_2015-12-31_WF to fix #232 I am stuck at the point where I need to setup a Property of Type Text first before running the test case.

I want to make sure that in SMW_DataValue.php at
https://github.com/SemanticMediaWiki/SemanticMediaWiki/blob/master/includes/datavalues/SMW_DataValue.php#L185
a text type value is parsed.

I have debugged quite a few test cases that come past this point but I just don't get how to create a Property first. The closest i could find are

  • the newDataValueProvider in SubobjectTest and
  • the FixtureProperties in Tests/Utils/Fixtures/Properties
  • the typeIdValueDataProvider in DataValueFactoryTest

How can I "create" and activate such a Property so that setting the value of the property in a test will make sure that the code for the corresponding SMW_DV_String.php class is called instead of SMW_DV_WikiPage which most of the tests end up with?

I am mostly confused by
SMW_DataItem and SMW_DataValue as outlined in:

https://www.semantic-mediawiki.org/wiki/Architecture_guide#SMWDataItem:_SMW.27s_way_of_representing_elements

https://www.semantic-mediawiki.org/wiki/Architecture_guide#SMWDataValue

I do not understand the complexity behind this. I'd like to create a Property of type Text as if I had created a property Page with content
[[has type::Text]]

This is the closest I could get so far:

       /*
     * test that <tag></tag> content can be parsed e.g. <pre>Some text</pre>
     * @since 2.4
     * @author Wolfgang Fahl
     */
    public function testTagParsing() {
        $property=PropertyValue::makeUserProperty('BarText');
        $property->setUserValue("[[has type::Text]]");

        $params = array( 'Foo=sometext','BarText=<pre>Some text</pre>');
        $expected = array(
                'errors' => 0,
                'propertyCount'  => 2,
                'propertyLabels' => array( 'Foo','BarText' ),
                'propertyValues' => array( 'Sometext','<pre>Some text</pre>' )
        );
        $this->testInstantiatedPropertyValues($params,$expected);
    }

The two lines

$property=PropertyValue::makeUserProperty('BarText');
$property->setUserValue("[[has type::Text]]");

seem to show my complete misunderstanding of how Property declaration in code works.

I can see that the json-script based tests described:
https://www.semantic-mediawiki.org/wiki/Help:Using_PHPUnit

would get me much closer to what I want. But there again a lot of complexity is added around handling the json so that this is too awkward an approach especially since I really want to programmatically create a property and understand how that works.

The PropertyRegistry class did not enlighten me either.
The static registerProperty($id,$typeid,$label, ....) function in SMW_DI_Property looks promising, but it says it's deprecated. The functio PropertyRegistry::registerProperty on the other hand is marked as being "internal only". This confuses me.

@mwjames
Copy link
Contributor

mwjames commented Jan 1, 2016

$property=PropertyValue::makeUserProperty('BarText');

Unless there is a specific test purpose, a DV (as in PropertyValue) shouldn't be constructed by hand and instead the DataValueFactory should be used.

$property->setUserValue("[[has type::Text]]");

This will not work, as this meant for the parser to handle and not to be used when constructing a DV.

How to setup a "Text" type property

A very simple example can be seen below (DI == is how the DB or storage engine sees an object, DV == is how an application interacts with an entity including, wikitext/html representation etc).

public function testTextDV() {

    $property = new DIProperty( 'Foo' );
    $property->setPropertyTypeId( '_txt' );

    // Using a dedicated property to created a DV
    $dataValue = DataValueFactory::getInstance()->newPropertyObjectValue(
        $property,
        'Some text'
    );

    $this->assertInstanceof(
        '\SMWStringValue',
        $dataValue
    );

    $this->assertEquals(
        'Some text',
        $dataValue->getDataItem()->getString()
    );
}

or as a more elaborate construct:

public function testTextDV() {

    $store = $this->getMockBuilder( '\SMW\Store' )
        ->disableOriginalConstructor()
        ->getMockForAbstractClass();

    $store->expects( $this->at( 0 ) )
        ->method( 'getPropertyValues' )
        ->will( $this->returnValue( array(
            new DIWikiPage( 'SomePropertyToBeBlob', SMW_NS_PROPERTY ) ) ) );

    $store->expects( $this->at( 1 ) )
        ->method( 'getPropertyValues' )
        ->with(
            $this->equalTo( new DIWikiPage( 'SomePropertyToBeBlob', SMW_NS_PROPERTY ) ),
            $this->anything(),
            $this->anything() )
        ->will( $this->returnValue( array(
            \SMWDIUri::doUnserialize( 'http://semantic-mediawiki.org/swivt/1.0#_txt' ) ) ) );

    // Inject the store as a mock object due to DIProperty::findPropertyTypeID finding the
    // type dynamically when called without explicit declaration
    ApplicationFactory::getInstance()->registerObject( 'Store', $store );

    // Create a DV from a string value instead of using a dedicated typed
    // property (used by #set, #subobject since the user input is a string and not
    // a typed object)
    $dv = DataValueFactory::getInstance()->newPropertyValue(
        'SomePropertyToBeBlob',
        'Some text'
    );

    $this->assertInstanceof(
        '\SMWStringValue',
        $dv
    );

    $this->assertEquals(
        'Some text',
        $dv->getDataItem()->getString()
    );

    // Reset instance to avoid issues with tests that follow hereafter
    ApplicationFactory::getInstance()->clear();
}

@mwjames mwjames closed this as completed Feb 3, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants