A couple of months ago I had a really interesting and very importatnt task. I had to code an automated process that creates Unirgy_DropshipPo purchase orders (Unirgy_DropshipPo_Model_Po objects). Because the task had a very high business value and everything had to work flawlessly, I decided to invest more energy and time in order to write a good test coverage with phpunit. I also knew that I needed tests because there was a big chance my code would be modified in the following weeks because of the business dynamics. I decided to “step” on something that I already knew how to utilise – EcomDev_PHPUnit ( Thank you Ivan Chepurnyi ).
Initially, my idea was to use EcomDev_PHPUnit only as a unit-testing tool and to test functions in isolation, but at a later stage of the development I found out that it would be even better if I used EcomDev_PHPUnit to test different branches of my algorithm.
During the development phase I had 3 main technical challenges:
- Unknown / Unexpected behaviour of Unirgy Dropship
- Collecting fixtures data in order to simulate test cases close to production environment
- Querying the database in order to prove that entities have been modified or created (Purchase order, credit memos and etc.)
1. Unknown / Unexpected behaviour of Unirgy Dropship
I was writing tests but at one moment I couldn’t continue because some of my tests were constantly failing.
The error message of the failing tests was: Unirgy_SimpleLicense_Exception: Module record not found: Unirgy_DropshipPo
The problem was coming from the fact that the Unirgy Dropship module has a license protection. While I was performing the test that invokes a method of some of the ionCube encoded classes (e.g. Unirgy_DropshipMulti_Helper_Protected) the Unirgy Dropship module was trying to do a license validation check (in my case the license validation check was failing). In the beginning it wasn’t so obvious to me because the error message / the exception was fired from ionCube protected class and couldn’t see from where it was trying to get the message “Module record not found: Unirgy_DropshipPo” from. I enabled SQL queries logging during the execution of the tests and found that Magento is trying to access 2 database tables that I wasn’t familiar with – usimplelic_license and usimpleup_module. In order to find a workaround for this license check, I had to copy the data of the 2 database tables (usimplelic_license and usimpleup_module) from my Magento to the phpunit database.
2. Collecting fixtures data in order to simulate test cases close to production environment:
Something that I really like in EcomDev_PHPUnit is the feature to store fixtures data in YAML files. The data from the YAML files is inserted in a separated phpunit database. This database is used only in the context of unit testing. I know that many developers disagree with the approach of storing fixtures data in the database and they will say that this is not unit testing. But we all know how highly coupled Magento is and for me personally this feature comes really handy.
Basically, it works like this:
- You store fixtures data in a YAML file.
- The data from the YAML file is inserted in a test database each time when you run test that is configured to use fixtures.
- After the test completes, EcomDev_PHPUnit truncates the tables used for the current test.
While I was testing different application branches, I used fixtures from a huge YAML file for the following tables:
eav: catalog_product: - entity_id: example-product-id type_id: simple … tables: sales/order: - entity_id: example-order-id state: "processing" … sales/order_address: - entity_id: example-order-address-id … sales/order_item: - item_id: example-order-item-id … sales/order_payment: - entity_id: example-order-payment-id … sales/invoice: - entity_id: example-invoce-id … sales/invoice_item: - entity_id: example-invoce-item-id … udpo/po: - entity_id: example-purchase-order-id … udpo/po_item: - entity_id: example-purchase-order-item-id … udropship/vendor: - vendor_id: example-udropship-vendor-id … udropship/vendor_product: - vendor_product_id: example-udropship-vendor-product-id … cataloginventory/stock_item: - item_id: example-stock-item-id …
As you can see, I used fixtures for 11 flat tables and some extra fixture data for catalog_product entities. Preparing all these fixtures was a lot of work but in the end I had the flexibility to test different business cases. Even more, I was able to easily convert live data to fixtures and recreate buggy behaviour.
3. Querying the database in order to prove that entities have been modified or created (Purchase order, credit memos and etc.):
Because of the specifics of Unirgy Dropship e.g. the ionCube protected classes I couldn’t mock so easily and test if an entity has been modified or created. I decided to query the database in order to check what is the outcome of the invoked functions from the ionCube protected class. Basically, the tests cases where I wanted to check if new purchase orders had been created were completing with something like this:
$collection = Mage::getModel('udpo/po’)->getCollection(); $this->assertEquals(3, count($collection));
Your thoughts / questions?