Sunday, September 2. 2007PHPUnit Database Extension (DBUnit Port)Trackbacks
Trackback specific URI for this entry
No Trackbacks
Comments
Display comments as
(Linear | Threaded)
I love it!
> For large test suites you may want to use a static singleton method of a test utility class to help get rid of some of the overhead of opening and closing connections
With a single connection there is a (small) risk that connection state left behind by one test might contaminate the next. More here: http://aperiplus.sourceforge.net/testing-data-access-classes.htm
That is a good point and definantly something that should be kept in mind when working with your test suites. It also makes another good point of the fact that it is safest to use a seperate connection for your fixture. Again because of the potential of auto insert IDs, affected rows, current errors etc.
Nice addition!
I wonder if inheritance (dbtestcase extending the regular one) is the Right Thing; I think people would need to use databases in existing testcases etc. Probably using a composition to do this would be cleaner. Is it also possible to use a 'fixture' like approach such as is common in ruby? Or php-based datasets instead of XML? That would make it easier to create pseudo-recent datasets such as 'create a record with its date set to yesterday'.
I am actually planning on slipping a method to add DB tests to existing test cases in before the 3.2 release. That is actually the purpose of the PHPUnit_Extensions_Database_*DatabaseTester classes.
I read a little bit about ruby fixtures and I am not sure what aspects of it you are wanting to use. I do have plans for adding a csv format to the dataset types as well as a composite dataset (to allow for combining multiple datasets.) I could also add a ruby fixture as a potential data set style. As far as loading fixtures in the ruby style, I don't know that I would want to depart that much from how PHPUnit already does things. If you have some more info that would helpful in understanding ruby fixtures that would help. Lasty there is sort of a way to build datasets in php using the DefaultDataSet/DefaultTable/DefaultTableMetaData classes. I will probably refine this to allow using a multi-dimensional array to create these data sets. IE $phpDataSet = $this->createPHPDataSet(array( 'table1' => array( array('col1' => 1, 'col2' => 2, 'col3' => 3), ... ), ... )); Thank you for the feedback it is extremely useful. If you have any other ideas feel free to open tickets at the PHPUnit Trac: http://www.phpunit.de/newticket
In ruby it's common to use 'YAML' as format for the fixtures; but the format isn't really that important. The important feature of fixtures is that you can have 'named sets'. For example, you could create 2 fixtures:
account: balance: 100 account_negative: balance: -100 When running testcases that do tests on accounts that have a negative balance, you'd tell your testcase to load 'account_negative' and your other testcases to use 'account'. This way, you can create specific sets of testdata for specific situations.
Great addition, thank you very much. Can't wait to start using it for our tests.
Is there a way (in this extension) that I easily can produce the XML-dataset seed from an existing database?
Not yet, but this is one of the features I have planned for the near future.
I wanted to be able to do this for use in our projects now so I have subclassed PHPUnit_Extensions_Database_DB_FilteredDataSet to create a new class WriteableFilteredDataset. To this I added a method writeFlatXmlDataset to write out an XML file that adheres to the FlatXMLDataSet XML structure. You can then load this using the standard Database TestCase delivered in Mike's work (ie using the createFlatXmlDataSet method).
I also subclassed PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection to create a new class SeedDatabaseConnection and added a new method called createWriteableDataSet which returns an instance of the aforementioned subclass WriteableFilteredDataset. Props to you Mike for keeping it extensible! So in your test suite you can create a new SeedDatabaseConnection object that connects to a seed database containing tables full of extractable data. Then when you want to, in your test cases you can extract the data you want out from the seed database into xml files and then load those xml files into the database that your tests are running against. So I guess my idea is to have this seed database that contains a clone of data from the production install. Then if you need some test data to run a certain test against you go into the seed database, refine that set of test data manually using SQL, then extract that refined data to xml files that your tests will use to set up their fixtures. Then you can refresh the seed database again from production and repeat the process to capture different test data sets when you need to. Does that make sense? If anyone is interested in the aforementioned subclasses I can send em...I'm contactable via the contact link on the workingsoftware website. cheers, dan
This is going to be a really useful addition to PHPUnit. I'm glad to see this get rolling.
Is there any significant advantage of using XML files to define the datasets, versus plain old PHP arrays? Personally, I would prefer just including PHP arrays instead. Also, I'm not familiar with Ruby and its testing systems, but I do like the idea of the named data sets mentioned by Ivo Jansch, above.
Hi, Is there any possibility to use PHPUnit for FTP
so I can test the connection and other stuff before using the real one. Greets ken,
It's probably me being stupid, but...
I don't really get it. You create a PDO-object and then you send it to the function you are testing. I am not prepared to rewrite my project to make all functions accept a PDO-object. What am I missing?
Can you give an example of what BankAccount() and createTable looks like?
you don't have to use a pdo object in the code you are testing. In fact it is preferred (imo) that you use a completely different connection anyways. I just used the same connection for brevity of the example.
The only requirement for PDO is for the setting up of the tests themselves. You are not required to use PDO in your code.
Ahh, you use the same object for both the system and the test.
Thanks for the answer! PS: When are you and Sebastian going to update the handbook? http://www.phpunit.de/pocket_guide/3.2/en/database.html
I came to your article from another article and am really interested in this learning about this. , I feel strongly about information and love learning more on this. If possible, as you gain expertise, It is extremely helpful for me.
would you mind updating your blog with more information?
Every public testWhatever() method tests some functionality of the class we want to test.
Do they all share the dataset returned by getDataSet()? Is there a way to specify different initial state for different testWhatever() methods? The initial state dataset is class-level or can it be method-level? Or maybe the latter is not a good idea whatsoever? I want to test a class that is like a finite state machine, and every testWhatever() method is a transition. Therefore, every test method focuses on a different initial state. If I design a class-level dataset as the union of the initial testmethod-level datasets, phpunit forces me to include them again in every final dataset to compare with -except the corresponding to the current test method, substituted by the end state of the transition. That's very verbose and redundant, and scales badly when you add test methods. Alternatively, I can use a test class for each test, but that's class-verbose; for a system class to test, I need as many test classes as functionalities I want to test; It doesn't look as a clean implementation of a unit test to me, does it? Thanks!
Thanks a lot for your work. It is very helpful.
I didn't find a way to build quickly a dataset from the database, so I develop the following php script. I hope it will be useful to some people... Cheers ! OS. [code] //Deals with the optional GET parameter $displayInBrowser = FALSE; $openMarkupChar = '
This is a really good read for me. Must agree that you are one of the coolest blogger I ever saw. Thanks for posting this useful information. This was just what I was on looking for. I'll come back to this blog for sure! I bookmarked this blog a while ago because of the useful content and I am never being disappointed. Keep up the good work
Im just wondering about performances on large sets of data.
If the test is done on a database containing a copy of the application in production, it may contain several thousand if not more lines of data. Dumping that into xml and comparing it with a reference xml is almost certain to have very poor performances, no ?
Oliver,
you are correct, this would have pretty severe performance implications. The idea is that you would have a smaller database with small datasets that allow you to test specific scenarios from the data stand point. Of course that's not to say you can't use a larger data set. This is possible to, you just have to understand the performance implications you are bringing up. What we do at my company is create a clean database with only reference data and then using dbunit we only populate the data required for the code to run.
Hello!
First I must say thanks for the great tutorial you wrote. I was ripping my hair off trying to get things to work, but I just can't do it! I wrote a test case in order to test some db data, following your tutorial. Everything I wrote is by the book, nothing exotic. But everytime I run phpunit I get this error: Class PHPUnit_Extensions_Database_TestCase could not be found in classitem.php What's wrong?? Please help me! Thanks in advance!!
What version of phpunit are you using and what is the command you are using to execute the test?
I had this problem too. For me, it was resolved by ensuring I had the filename of my test case the same as the test class name, e.g. filename BankAccountDBTest.php. I notice your error message mentioned classitem.php, is this the name of your class?
Thanks for the comment about the class name and file name needing to match! Very helpful, the error message isn't helpful in determining this cause.
Is there any reason for the requirement? I'm working with some legacy code, and now have to have multiple coding styles and naming schemes (renaming all existing files, functions, and classes to match this is not an option). I can understand the coding style, but I don't understand why it should be enforced. Either way, it would be helpful to mention this in the documentation. Thanks for the extension, aside from the above, so far it looks good!
Hi Mike,
Thanks for this great missing feature in PHPUnit. Just as mjimenez I would like to know why I'm limited to only call one xml seed file per test class? Some test methods might require different sets of data. And also, when you seed your test DB with createFlatXMLDataSet() and you're doing inserts, updates or deleting from a table that is not in the seed XML file, it will use the real database. IMO this causes confusion as failure to remember to include a table in the XML file will have unexpected results for the end-user. Could you please clarify these two issues Mike? Thank you.
The reason why you are limited to one dataset is for simplicity. Your test cases as far as database testing is concerned should revolve around using a common dataset.
I don't quite understand what your second comment is about. All I can say is PHPUnit can't do what you don't tell it to in regards to setting up the database. Imo it would cause significantly more confusion if tables were getting truncated when you told it not to. Lastly, the schema parameter is necessary to be able to do ither required introspection on the database. There is no sql standard way to pull your current schema nor is there a way to pull this information from PDO, and it is actually sqlite that this does nothing for
Oh and one more thing...
The second argument on method createDefaultDBConnection() is required but doesn't seem to be doing much when not using SQlite.
i am getting this error " Class 'PHPUnit_Extensions_Database_DataSet_FlatXMLDataSet' not found"
i have that class avaialble .. not sure what is wrong. Please help Manasi
Lowercase the ML of XML, so :
PHPUnit_Extensions_Database_DataSet_FlatXmlDataSet
come on people.. why there is not a word about that database structure must exist before running tests!?
Largely a lack of time on my part. There will be a fairly thorough description of this functionality in a soon to be released book. I am also attempting to put some more time in on my personal projects which would include some long awaited documentation and bug fixes. I have to feed the family first
Yes its a great article as well aspects and this is the virtual thing .
php is really complex, yet i still find myself reading high quality articles like this. many thanks
I liked this post. It is helping to learn some more about PHP.
It works especially if you add the data specification codes in the 2nd line of the unit. Thanks for this info.
This is my first time i have visited here. I found many interesting stuffs in your article. Well-done!
Just read your post and would like to thank you for maintaining such a cool blog.
initial state dataset is class-level or can it be method-level? Or maybe the latter is not a good idea whatsoever?
bank account with a zero balance in the database. To test this we will need to create another dataset representing our seed data with the expected changes.
Great! Thanks for the great article posting and your all effort. I think the above article is valuable for all concerned people about this topics. For me the Informations are really really useful for my research. I’ve Bookmarked this page for future reference.
Nice effort, very informative, this will help me to complete my task.
This is a very good blog just full of useful information. thanks for sharing this post.
There’s an unbroken kind of the quantity of a bag that has a striking flower on the matter of matching bag with adjustable straps and numerous compartments in it. Next, deem your clothing.
Full Lace Front Wig, Long & Short Hair Wigs: 80% OFF at Celebrity Wigs. We ensure 100% customer satisfaction with our Long & Short Indian Remy Hair Wigs.
I am very interested in your article, I think your articles are so interesting that I need more information, go is berkaya and I will always support you. I say many thanks to you.
Good! And for that I’ll give you a comment! I’ll get back here and comment again if the Techniques work.
I'm really very useful to follow a long-time see this as a blog here. Thank you for your valuable information.
Hey, your site is really great, I came across while in search for brand info on bing and it has lots of related information on it. Will be sure to come back again and bookmark. Keep up the great work!
Will be sure to come back again and bookmark. Keep up the great work!Hey, your site is really great, I came across while in search for brand info on bing and it has lots of related information on it.
The element name is equal to the table name the row resides in. The element will have one attribute for each column in the table.
Great information! I just want you to know that this blog really gonna help me to broaden my knowledge.
I would like to test in this example is testing new account creation.
I don't know that I would want to depart that much from how PHPUnit already does things.
|
Paying for the Site
QuicksearchCategoriesArchivesDaily ReadsThe PHP WTF Sebastian Bergmann Wez Furlong Tom Sommer Tobias Schlitt Chris Shiflett Ben Ramsey adam trachtenberg Sklar george schlossnagle Dynamically Typed (Harry Fuecks) John Coggeshall John Lim Marco Tabini PHP Application Tools Planet PHP PHPCommunity.org |

