Note that I’m not accessing the code directly in the test, but I am in the 
extension object I’m testing.

Yeah, my code is not great, although this is actually legacy from one of my 
former people. A lot of what you point out should be cleaned up, but I didn’t 
want to do that here in case it was related to why things were acting up. I was 
wondering about that $thrown myself.

Jim


> On Sep 27, 2017, at 11:04 AM, Florian Schmidt 
> <[email protected]> wrote:
> 
> Hi!
> 
> First of all: You should try to avoid accessing the database in tests, if 
> possible. E.g. separating the logic of your extension from the database code. 
> If you really need the DB, the Database section of the Writing unit test page 
> on mediawiki.org[1] should explain how you can make the database table 
> available during test and how to use it.
> 
> Another common way of writing tests without relying on the database is to 
> mock objects and simulate how objects, on which the code under test relies 
> on, behaves under defined circumstances. For more information see the PHPUnit 
> Test doubles page[2].
> 
> One hint unrelated to your question: The code you pasted looks a bit 
> confusing: You throw an exception (there's only one place where it is thrown 
> from the code you're showing in this method) directly inside a try/catch 
> block, which only catches this exception. That doesn't make much sense, I 
> would recommend to directly do what you need to do in the error case. Also: 
> Why do you check for a local variable $thrown, which can only be set inside 
> the catch block as the last statement of the method?
> 
> [1] 
> https://www.mediawiki.org/wiki/Manual:PHP_unit_testing/Writing_unit_tests#Databases
>  
> [2] https://phpunit.de/manual/current/en/test-doubles.html
> 
> Best,
> Florian 
> 
> -----Ursprüngliche Nachricht-----
> Von: Wikitech-l [mailto:[email protected]] Im Auftrag 
> von Jim Hu
> Gesendet: Mittwoch, 27. September 2017 17:31
> An: Wikitech mailing list <[email protected]>
> Betreff: [Wikitech-l] Writing unit tests for extensions that use dbr calls
> 
> I’m trying to improve my coding practices for our MW extensions, and I’m very 
> confused by whether my problem with PHPUnit is a problem with the test I’m 
> writing or with the extension object class I’m trying to test.
> 
> My extension uses some custom database tables to store the properties of 
> objects that are created during execution. In older versions of MW, I could 
> just create an object and test that the methods of the object class returned 
> appropriate values for known data that was already in the database. Now, 
> instantiating an object is creating temporary tables that don’t exist and 
> causing fatal errors. Example:
> 
> 7) CacaoModelAnnotationTest::testNewCacaoModelAnnotationSuccess
> Wikimedia\Rdbms\DBQueryError: A database query error has occurred. Did you 
> forget to run your application's database schema updater after upgrading? 
> Query: SELECT  
> annotation_id,row_id,original_row_data,annotation_timestamp,user_id,team_id,session_id,annotation_inning
>   FROM `unittest_cacao_annotation` INNER JOIN `unittest_cacao_user` ON 
> ((annotation_user = cacao_user.id))   WHERE annotation_id = "6057"  
> Function: CacaoModelAnnotation::load
> Error: 1054 Unknown column 'cacao_user.id' in 'on clause' (localhost)
> 
> This is the load method from class CacaoModelAnnotation:
> 
>       public function load() {
>               try{
>                       wfProfileIn( __METHOD__ );
>       
>                       if ( $this->loaded ) {
>                               return false;
>                       }
> 
>                       MWDebug::log( __METHOD__ . ' called for annotation_id: 
> ' . $this->id );
> 
>                       $dbr = wfGetDB( DB_SLAVE );
>               
>                       // query to get annotation attributes
>                       $result = $dbr->select(
>                               array( 'cacao_annotation', 'cacao_user' ),
>                               array( 
>                                       'annotation_id', 'row_id', 
> 'original_row_data',  'annotation_timestamp', 
>                                       'user_id', 'team_id', 'session_id', 
> 'annotation_inning'
>                               ),
>                               'annotation_id = "' . $this->id . '"',
>                               __METHOD__,
>                               array(),
>                               array(
>                                       'cacao_user' => array('INNER JOIN', 
> 'annotation_user = cacao_user.id' ),
>                               )
>                       );
>                       if ( $dbr->numRows($result) == 0 ) {
>                               throw new CacaoException( 
> wfMessage('cacao-annotation-load-returned-zero-rows', $this->id)->text() );
>                       }
>                       $resultRow = $dbr->fetchObject( $result ); 
>                       $this->loadFromResultRow($resultRow);
>               
>                       wfProfileOut( __METHOD__ );
>               }catch(CacaoException $e){
>                       if(!isset($thrown)){
>                               throw $e;
>                       }
>                       $thrown = true; 
>               }       
>       }
> 
> Is there a good example of an extension that uses custom database tables that 
> I can use as a role model?
> _______________________________________________
> Wikitech-l mailing list
> [email protected]
> https://lists.wikimedia.org/mailman/listinfo/wikitech-l
> 
> 
> _______________________________________________
> Wikitech-l mailing list
> [email protected]
> https://lists.wikimedia.org/mailman/listinfo/wikitech-l


_______________________________________________
Wikitech-l mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/wikitech-l

Reply via email to