TDD: Test MVC application - php

I've started from scratch a new application using TDD and PHPUnit. It is going to be a MVC application. I've started my tests from the Model. That was fun and i didn't have too much problems.
Now I want to create my views/models. But the question is: How do I test my controllers? What about views? My controller will use my tested models and my future views.
Thanks.

There are three broad categories of testing for each of the layer in the MVC. The unit tests for models, functional tests for the controllers and the UI testing for the views.
Unit tests are the easiest to write. They are cheap in terms of time and do not require too many dependencies to be stubbed/mocked.
Functional tests on the other hand are a bit expensive compared to an unit test. In a given scenario, if you had covered enough in your application for the models using unit test, you can relax a bit in the functional testing part. However, you should still be having a good code coverage - 100% to be ideal for your controller methods as well.
The last is the UI testing which is the costliest of all tests. You can probably use Selenium for browser based testing and try to automate it with your language. You may have to have a RC sever running in the background to achieve this. But trust me, if you cover the first two parts - unit and functional, this can be made optional if not no.
And it is advised to have a CI - Continious Integration setup with a code coverage utility that gives a trending on the % of code covered through tests.

When you are running the tests , you should be using only the class under test. Other objects should be replaced with mocks or other fake structures.
You do this, because ( for example ) when you write a test for controllers action , you will have provide some values for said action, and then check if the correct data is passed to the view and models.
This is one of the reasons why you should avoid use of global state ( in form of static calls or global variables ) in your code.
Some links you might find useful
The Clean Code Talks - Unit Testing
The Clean Code Talks - Global State and Singletons
The Clean Code Talks - Don't Look For Things!

Related

Creating a fake user in Symfony2 for testing purposes

I'm somewhat new to testing in PHP. I've done quite a bit of testing on Rails using Cucumber, RSpec, Capybara and Factory Girl, but I've barely done any testing with PHP.
I'll ask a question about my current challenge in the most general way possible, since I've gone down a few specific paths and been met only with frustration.
I want to write a functional test for signing a user in. What's a good way to create the test user object that I would need in order to try to sign in?
Even more generally, what's the de facto standard for creating test objects in Symfony2? Fixtures? Some kind of factory?
In Ruby, I would use Factory Girl, since it lets you handle any object's dependencies in a clean, DRY way. There seems to be a Factory Girl equivalent in PHP in Phactory, but unfortunately it seems that that tool is not widely used and no longer maintained.
Fixtures on a test environment configuration are probably the way to go!
About the fixtures being application-wide comment, I disagree.
If you were unit testing, maybe that would make a lot of sense.
Functional tests, however, are supposed to be application-wide.
I just write test data builders myself, because there is almost no boilerplate anyway. BTW, Factory Girl is an implementation of that very pattern.
You can find a good discussion of the pattern and a lot of other useful stuff in the Growing Object-Oriented Software, Guided by Tests book.
And I recommend against fixtures, because they are application-wide. Each test better prepare only the data it needs for itself.
I use fixtures for functional tests but i disagree that they are application wide only. Im using it bundle-wide, defined in proper dirs in bundles. On test setup i run console fixtures:load method from proper directory and maybe not best solution but it works good for me. If anyone have better solution i would happily read about it :)

Zend Unit Test with database

I want to make some unit tests in my project (i am new to testing), but tutorials online seem to show examples testing only simpliest stuff.
What I want to test is case when after sending POST to addAction in my SurveyController will result in adding corresponding rows to my survey and question tables (one-to-many).
What are the best practices to test database related stuff? Do I create separate db for my test environment and run tests on it? That is the only and right option?
It depends on your circumstances.
Here is my take on this:
The idea is to test but also be DRY (Don't repeat yourself). Your tests must cover all or as many different cases as possible to ensure that your component is thoroughly tested and ready to be released.
If you use an already developed framework to access your database like Doctrine, Zend Framework, PhalconPHP etc. then you can assume that the framework has been tested and not test the actual CRUD operations. You can concentrate on what your own code does.
Some people might want to test even that but in my view it is an overkill and waste of resources. One can actually include the tests of the particular framework with their own if they want to just have more tests :)
If however you were responsible for the database layer classes and its interaction with your application, yeah tests are a must. You might not run them all the time you need to prove a database operation works or not through some piece of code, but you need to have them.
Finally you can use Mock tests as Mark Baker suggested in your code and assume that the database will respond as you expect it to (since it has already been tested). You can then see how your application will react with different responses or results.
Mocking database operations will actually make your tests run faster (along with the other benefits that come with this strategy) since there won't be any database interactions in the tests themselves. This can become really handy in a project with hundreds if not thousands of tests and continuous integration.
HTH

PHP Unit Testing without a framework... Possible? Advisable?

When one starts searching for PHP unit tests, one usually stumbles upon:
PHPUnit.
SimpleTest.
A plethora of blogs explaining how to use PHPUnit and SimpleTest.
StackOverflow questions about PHPUnit and SimpleTest...
...and I think you get the idea.
I was wondering: How does one go about unit testing with plain ol' PHP? Is that even a wise endeavor?
I suppose I would have to build my own little framework. I'm interested because I want to have a better understanding of what's going on in my unit tests. I'm also interested because I think a lightweight, tailored solution would run my tests faster.
Bonus question: Who's the underdog? Is there a third framework worth looking into (for acedemic purposes)?
Unit testing is basically a set of assertions.
Consider the following PHPUnit test case:
class MyTest extends PHPUnit_Framework_TestCase {
public function testFoo() {
$obj = new My;
$this->assertEquals('bar', $obj->foo());
}
}
You can have a similar test case without using PHPUnit:
class MyTest {
public function testFoo() {
$obj = new My;
assert("$obj->foo() == 'bar'");
}
}
However, by doing it without a framework, you will have to manually create an instance of the test case (MyTest) and call each test method manually (MyTest::testFoo, etc.).
The framework (e.g.: PHPUnit) is nothing more than a set of "helpers" to make it easier and faster: by automatically generating skeleton; with built-in mock objects, command lines scripts, etc.
You can still unit test without a framework, but in the end, you'll probably save more time using one, because after all, that's generally what frameworks are for.
My view would be what's so wrong with the standard wheel (PHPUnit in all probability) that warrants the development of a replacement? After all, Isn't a proven solution the wiser choice in this instance?
Additionally, the output of the standard tools will be easier to use if you ever want to take advantage of a Continuous Integration server further down the line. (You could of course make your own tool output in an identical format, but that leads me back to the "why re-invent the wheel" argument.)
I've used SimpleTest about a year ago and it's very lightweight. There really wasn't much to it except providing you a way to auto-load test packages and assert.
Essentially it included all classes starting with "test" and it would call all methods starting with "test" inside that class. Inside the methods you could assert the results are what you expected.
If you were to build your own framework, I would strongly recommend looking into SimpleTest before. It's very lightweight compared to PHP Unit (if that's what scares you).
You can write tests in any language without a framework, but the code you write that you share in your tests will end up being a kind of mini-framework anyhow.
A good unit testing framework will have the common stuff that you need to make testing easier, such as assertions, mocks, stubs, exception handling and code coverage.
Bonus question: Who's the underdog? Is there a third framework worth looking into (for acedemic purposes)?
There are underdogs in the PHP unit testing space, for example Enhance PHP, which is a unit-testing framework with mocks and stubs built in. It has some advantages over the big players - it has good documentation and is very quick to get started on.

Should controllers in MVC web applications be unit-testable?

It seems to me that web developers of different programming languages often share different opinions on this. For example, Ruby web developers (with Rails being the dominant framework) appear to think of controllers as glue code, which should have functional tests, but not unit tests. A similar attitude dominates in the PHP world, yet there has been some initiative (e.g. Symfony2).
However, it also seems that, for example, some ASP.NET MVC developers actually want their controllers to be unit-testable.
What I'd like to know is if that actually works in web development. Are controllers worth unit testing? Does designing them to be unit-testable noticeably cripple development speed in non-trivial applications? Also, have any web frameworks tried to enforce controller unit-testability? Personal experiences are welcome.
Short answer: "Yes" with an "If," long answer: "No" with a "But."
These days I tend to miss controller-level unit tests in favour of strong unit-test coverage of models and business objects and functional-test coverage with Cucumber. The assumption here is that the controllers are very light-weight objects routing data into underlying models that encapsulate the vast majority of business logic.
However, I still do tend to have some very light coverage of some of the control flow at the controller level. It just tends to be more of a sanity-check.
One of the issues with controller-level testing is that you often either have to mock or generate a large number of models and objects in order to test effectively. Given this, I find it more valuable to push these tests up into the functional layers where the style of testing allows you to more efficiently express these dependencies (either by explicitly following the steps required to generate them through your application itself or through a system like Cucumber's declarative rules).
Everything is worth to be unit tested. In this case it depends on how much of the logic is realized in the controllers... In small project you can have no external logic attached and you may want to make some of the database operations in your controller (like on many Microsoft examples). In bigger solutions you may not need to test the controller as far as it's job is just to invoke specified business logic methods... It's not about if controllers are worth to be unit tested, it's about if the code that they contains is...
One of the best features of the MVC pattern is that the controllers can be tested in isolation of the HTML output by the views. Pages that mix the logic with the HTML output are hard to test, and this is one of the problems that MVC solves - it makes your controller all about logic and you can test it without parsing HTML at all.
Ideally, your controller will get data from separate data access classes, which you can stub out for your tests, so you are just testing the logic. Essentially you isolate your controller from the database in the same way MVC isolates it from the view - then the tests are easy because you don't need a database with test data either.

Unit Testing CodeIgniter with Simpletest - very few tests

On our development team, we decided to give Unit Testing a try. We use Simpletest. However, it's been a tough road. After a week, I only have created 1 unit test that tests a certain helper file. That's it. The rest (controllers, models, views, libraries) don't have unit tests yet. And I plan to not test a majority of them. Views, for example, are too trivial to test, so I pass up on testing that. Next, the controllers. I plan my controllers to not do complex stuff, so that it only does passing of information between the models and the views. I'd move those more complex stuff to libraries or helpers.
Now for my questions:
1) Am I doing it wrong? So far, there's nothing more that I can see that can be erroneous so it would need a unit test. Most of the stuff (right now) are just CRUD.
2) Do we really need to unit test controllers? Since a controller's job is just minor processing of data passed between View and Model, I find very little initiative in unit testing it.
3) If I use WebTestCase to test for controllers, would that be still considered a Unit Test? Or is it already an integration test?
4) Suppose you got me to test my controller, how would I test it? As far as I know, CI follows the Front Controller pattern through index.php, so how would I handle (mock?) that?
If you are still open with suggestion to another unit test for CodeIgniter, I suggest you try Toast. I found it easy to use, and not interfere much with my development process.
I only use unit test to test my library, helper, and model. My controller not have much code, only get post and uri parameter, sanitizing it using trim or intval, pass it to library or model, then pass the result to view.
View almost have none code to test, since it display everything to browser. Mostly, it just need css and js debugging.
Model almost always need testing, since it dealing with data. Without unit test, I found it difficult to trace some bug, specially with a complex computation.
Library and helper do a repetitive task, so it need a unit test to make sure the logic in it is doing the work correctly.
I hope this help.
Are you doing something wrong? I don't think so.
Do we really need to unit test controllers? I don't. Maybe I should. Seems like a lot of work, though.
If I use WebTestCase to test for controllers, would that be still considered a Unit Test? Or is it already an integration test? WebTestCase would be an interesting approach to testing controllers if some meaningful output could be detected; for example, detecting that no error has occurred when calling /some/specific/path.
Suppose you got me to test my controller, how would I test it? That's a tough one. You would presumably need to initialize part of the application environment in order to do anything worthwhile.
Most articles/books tell you to define your tests before you start coding. Maybe I've tried that, but I'm usually too impatient. It seems to get in the way of quick prototyping, but maybe defining the unit tests is a way of quick prototyping.
I've found that deciding what to test with PHP is a challenge. I think you have to pick your battles. If it's critical that a method return a value of specific type, then test for that. If a lot of things happen automatically when instantiating an object, you could test for that too.
In general, what I do -- right or wrong -- is get everything working, then create some basic tests and then add tests as needed based on any problems I encounter. The idea is to never have a repeat problem and each test will insure that the application behaves the same through its life-cycle.
As for specifics, I'm using Zend Framework, but it will be similar in CodeIgniter. I also use SimpleTest (but with my own class wrapper). I may or may not unit test models and I have never implemented tests for controllers or views; it's seems like too much work and too little benefit. Most frameworks "fail early" and so issues are typically obvious. But any common library code make for easier targets and bugs here -- especially logic bugs -- are harder to detect. Set up your tests to make sure things work as expected so that your framework-specific code encounters few problems.

Categories