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 :)
Related
I'm already writing some unit tests for the critical business logic of my projects and I am aware of the concept and the pros and cons of TDD - I just never really went "all the way TDD" with writing tests first and stuff. I am currently working on a medium-sized project that I didn't develop myself and this is quite horrible to work with: No tests at all, tightly coupled architecture, no dependency injection, legacy MVC framework, and so on - less than ideal. I am considering just starting from scratch using Laravel or Symfony and applying TDD to really achieve loose coupled and testable code.
I know that it's probably not a good idea just to dive head first into TDD with such a "large" project, so I was thinking that I'd do a couple of test projects to see how TDD affects my code design and quality. For the sake of it, let's assume it's just some kind of "movie-rental-application-thing" with user registration and a function to rent a movie if that is available. Let's also assume that I already did some UML diagrams and I have some ideas about the required objects, their relations and the required business logic.
So: Where to start? When talking to people who do TDD on MVC frameworks, some people tend to "isolate" a function of the business logic and start up with an acceptance test, the function being "Show list of available movies" and the test being like "Navigate to /movies and assert against some HTML" or whatever. To me, this doesn't feel like a good start.
Personally, I like to start with features like user login or user management - pretty much stuff that is rather supporting the application than being business logic itself. If I was to use that approach, wouldn't I be deliberately ignoring functions that I already know I will require? Let's pretend the movie-list test works, so I'd add another test like "OnlyLoggedInUserCanSeeMovieList", see it fail and add the logic to the code - the logic I KNEW I would need even before I wrote the first test at all. I find it hard to believe that this would lead to a better code as I'm deliberately not implementing functions that I'm already aware of.
Is this just up to personal preference or is there something like a best practice to get me started? How do you guys start with TDD in a framework like Symfony or Laravel? Is there even a point in doing pure TDD in such cases, seeing that a whole lot of application logic is already handled and tested by the framework itself? Don't get me wrong: I don't want to start another war about pros and cons of TDD - I'm sure there are pros I can benefit from once I get my head around this completely. Nonetheless, right now this feels like a ridiculous amount of micro-progress on rather simple functionality and I feel I'd be better of just unit testing important parts of application logic instead of doing all the "Write test, see it fail, write code, refactor" iterations.
Thanks for some input,
Chris
I would say first you need to do some research to find the bundles you will be using.For example you say that you'd rather start unit testing your user management, except in fSymfony you already have great user management bundles that already come with their test series.
So i would say the first step when starting youre project is to find what already exists and would fit your needs. After abstracting the most you can it should be simpler to see where to start (usually writing tests to make sure all the bundles you are using work properly together).
Hope that helps you get started
What I'm looking for is a way to remove the model from a set of PHP files that make up a website. It's difficult (for me) to explain.
By models I mean models in an MVC sense.
As an example say I have this website:
index.php
about.php
shop.php
checkout.php
All of the above PHP files use the same database. I have separated the views by adding templates using a view.php file that renders the correct template with values passed to it.
I am not looking to use a framework that's already out there. I'm looking at writing my own in some senses, with only the bits I need to use in it.
If anyone would like to explain why this is not necessary, or a better way of doing things, then I'm open to that too.
Thanks in advance.
Writing you own MVC framework will take time, but you will learn a lot in the process. So, if you have the time/resources to do it I definitely encourage you to do so.
In this context here are some small pieces of advise that may help you:
Create your domain model first. I'm assuming that you are going in the OO way, so think about your domain problem and create the abstractions that best represent your problem. Try to keep it decoupled from cross-cutting concerns, like persistence.
Test a lot, test often. Try to test (and run your tests) as you create your domain model. This will be specially valuable when in 6 months you add a new feature and want to make sure that you haven't break anything. If you can separate your domain model from anything external (like the persistence layer or third party web services) the testing it is going to be a lot simpler. Today PHPUnit is pretty much the de-facto standard for unit testing in PHP.
You don't have to write everything from scratch. There are a lot of libraries that can help you to ease the development of an MVC framework, so that you can concentrate on what you really want to develop. For example, you could use Slim to handle the page routing or you could delegate the persistence stuff to Doctrine 2.
It is always nice to analyze how other frameworks solve things. You may want to look at products like Symfony or Kohana or even check how Elgg handles its views system. Also, if you want to check out something radically different you can take a look at Seaside's architecture.
Coming back to your original question, for me the key is to keep things from different layers as decoupled as possible. While I have only used the version 1, Doctrine 2 seems like a good candidate for persistence, since it allows you to create a domain model that is quite independent from the DB. This is a huge step. The second thing is how handle the view system. This is quite developer-taste dependent. For example, I like to model everything with objects, so I like Seaside's approach. On the other hand, Elgg's way of handling views is quite nice and maybe fits better with the way things are handled in PHP. Here is when you may benefit on doing some research before deciding on a route to go.
HTH
As someone who has written his own PHP framework, and with the same sensibility as yours, I can tell you that using a framework is a fine thing to do. That said, start by writing your own - you'll gain greater appreciation for the true structure and utility of a framework.
You'll want to learn about the Singleton object pattern. It is a major differentiator in the kinds of objects you can develop in your framework.
When you have written a few models that your files/controllers (presuming MVC) include, you will begin to see where to abstract a 'base mode' from which others extend (hint: the DB singleton).
When you start pulling in configs and the like, then you'll have your first framework object from which all other bases do their extension.
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.
I've got a big project written in PHP and Javascript. The problem is that it's become so big and unmaintainable that changing some little portion of the code will upset and probably break a whole lot of other portions.
I'm really bad at testing my own code (as a matter of fact, others point this out daily), which makes it even more difficult to maintain the project.
The project itself isn't that complicated or complex, it's more the way it's built that makes it complex: we don't have predefined rules or lists to follow when doing our testing. This often results in lots of bugs and unhappy customers.
We started discussing this at the office and came up with the idea of starting to use test driven development instead of the develop like hell and maybe test later (which almost always ends up being fix bugs all the time).
After that background, the things I need help with are the following:
How to implement a test
framework into an already existing
project? (3 years in the
making and counting)
What kind of frameworks are there
for testing? I figure I'll need one
framework for Javascript and
one for PHP.
Whats the best approach for testing
the graphical user interface?
I've never used Unit Testing before so this is really uncharted territory for me.
G'day,
Edit: I've just had a quick look through the first chapter of "The Art of Unit Testing" which is also available as a free PDF at the book's website. It'll give you a good overview of what you are trying to do with a unit test.
I'm assuming you're going to use an xUnit type framework. Some initial high-level thoughts are:
Edit: make sure that everyone is is agreement as to what constitutes a good unit test. I'd suggest using the above overview chapter as a good starting point and if needed take it from there. Imagine having people run off enthusiastically to create lots of unit tests while having a different understanding of what a "good" unit test. It'd be terrible for you to out in the future that 25% of your unit tests aren't useful, repeatable, reliable, etc., etc..
add tests to cover small chunks of code at a time. That is, don't create a single, monolithic task to add tests for the existing code base.
modify any existing processes to make sure new tests are added for any new code written. Make it a part of the review process of the code that unit tests must be provided for the new functionality.
extend any existing bugfix processes to make sure that new tests are created to show presence and prove the absence of the bug. N.B. Don't forget to rollback your candidate fix to introduce the bug again to verify that it is only that single patch that has corrected the problem and it is not being fixed by a combination of factors.
Edit: as you start to build up the number of your tests, start running them as nightly regression tests to check nothing has been broken by new functionality.
make a successful run of all existing tests and entry criterion for the review process of a candidate bugfix.
Edit: start keeping a catalogue of test types, i.e. test code fragments, to make the creation of new tests easier. No sense in reinventing the wheel all the time. The unit test(s) written to test opening a file in one part of the code base is/are going to be similar to the unit test(s) written to test code that opens a different file in a different part of the code base. Catalogue these to make them easy to find.
Edit: where you are only modifying a couple of methods for an existing class, create a test suite to hold the complete set of tests for the class. Then only add the individual tests for the methods you are modifying to this test suite. This uses xUnit termonology as I'm now assuming you'll be using an xUnit framework like PHPUnit.
use a standard convention for the naming of your test suites and tests, e.g. testSuite_classA which will then contain individual tests like test__test_function. For example, test_fopen_bad_name and test_fopen_bad_perms, etc. This helps minimise the noise when moving around the code base and looking at other people's tests. It also has then benefit of helping people when they come to name their tests in the first place by freeing up their mind to work on the more interesting stuff like the tests themselves.
Edit: i wouldn't use TDD at this stage. By definition, TDD will need all tests present before the changes are in place so you will have failing tests all over the place as you add new testSuites to cover classes that you are working on. Instead add the new testSuite and then add the individual tests as required so you don't get a lot of noise occurring in your test results for failing tests. And, as Yishai points out, adding the task of learning TDD at this point in time will really slow you down. Put learning TDD as a task to be done when you have some spare time. It's not that difficult.
as a corollary of this you'll need a tool to keep track of the those existing classes where the testSuite exists but where tests have not yet been written to cover the other member functions in the class. This way you can keep track of where your test coverage has holes. I'm talking at a high level here where you can generate a list of classes and specific member functions where no tests currently exist. A standard naming convention for the tests and testSuites will greatly help you here.
I'll add more points as I think of them.
HTH
You should get yourself a copy Working Effectively with Legacy Code. This will give you good guidance in how to introduce tests into code that is not written to be tested.
TDD is great, but you do need to start with just putting existing code under test to make sure that changes you make don't change existing required behavior while introducing changes.
However, introducing TDD now will slow you down a lot before you get back going, because retrofitting tests, even only in the area you are changing, is going to get complicated before it gets simple.
Just to add to the other excellent answers, I'd agree that going from 0% to 100% coverage in one go is unrealistic - but that you should definitely add unit tests every time you fix a bug.
You say that there are quite a lot of bugs and unhappy customers - I'd be very positive about incorporating strict TDD into the bugfixing process, which is much easier than implementing it overall. After all, if there really is a bug there that needs to be fixed, then creating a test that reproduces it serves various goals:
It's likely to be a minimal test case to demonstrate that there really is an issue
With confidence that the (currently failing) test highlights the reported problem, you'll know for sure if your changes have fixed it
It will forever stand as a regression test that will prevent this same issue recurring in future.
Introducing tests to an existing project is difficult and likely to be a long process, but doing them at the same time as fixing bugs is such an ideal time to do so (parallel to introducing tests gradually in a "normal" sense) that it would be a shame not to take that chance and make lemonade from your bug reports. :-)
From a planning perspective, I think you have three basic choices:
take a cycle to retrofit the code with unit tests
designate part of the team to retrofit the code with unit tests
introduce unit tests gradually as you work on the code
The first approach may well last a lot longer than you anticipate, and your visible productivity will take a hit. If you use it, you will need to get buy-in from all your stakeholders. However, you might use it to kickstart the process.
The problem with the second approach is that you create a distinction between coders and test writers. The coders will not feel any ownership for test maintenance. I think this approach is worth avoiding.
The third approach is the most organic, and it gets you into test-driven development from the get go. It may take some time for a useful body of unit tests to accumulate. The slow pace of test accumulation might actually be an advantage in that it gives you time to get good at writing tests.
All things considered, I think I'd opt for a modest sprint in the spirit of approach 1, followed by a commitment to approach 3.
For the general principles of unit testing I recommend the book xUnit Test Patterns: Refactoring Test Code by Gerard Meszaros.
I've used PHPUnit with good results. PHPUnit, like other JUnit-derived projects, requires that code to be tested be organized into classes. If your project is not object-oriented, then you'll need to start refactoring non-procedural code into functions, and functions into classes.
I've not personally used a JavaScript framework, though I would image that these frameworks would also require that your code be structured into (at least) callable functions if not full-blown objects.
For testing GUI applications, you may benefit from using Selenium, though a checklist written by a programmer with good QA instincts might work just fine. I've found that using MediaWiki or your favorite Wiki engine is a good place to store checklists and related project documentation.
Implementing a framework is in most cases a complex task because you kinda start rebuilding your old code with some new solid framework parts. Those old parts must start to communicate with the framework. The old parts must receive some callbacks and returnstates, the old parts must then somehow point that out to the user and in fact you suddenly have 2 systems to test.
If you say that you application itself isn't that complex but it has become due to lack of testing it might be a better option to rebuild the application. Put some common frameworks like Zend to the test, gather your requirements, find out if the tested framework suits for the requirements and decide if it's usefull to start over.
I'm not very sure of unit testing, but NetBeans has a built-in unit testing suite.
If the code is really messy, it's possible that it will be very hard to do any unit testing. Only sufficiently loosely coupled and sufficiently well designed components can be unit tested easily. However, functional testing may be a lot easier to implement in your case. I would recommend taking a look at Selenium. With this framework, you will be able to test your GUI and the backend at the same time. However, most probably, it won't help you catch the bugs as well as you could with unit testing.
Maybe this list will help you and your mates to re-structure everything:
Use UML, to design and handle exceptions (http://en.wikipedia.org/wiki/Unified_Modeling_Language)
Use BPMS, to design your work-flow so you won't struggle (http://en.wikipedia.org/wiki/Business_process_management)
Get a list of php frameworks which also support javascript backends (e.g. Zend with jQuery)
Compare these frameworks and take the one, which matches the most to your project desgin and the coding structure used before
You should may be consider using things like ezComponents and Dtrace for debugging and testing
Do not be afraid of changes ;)
For GUI testing you may want to take a look at Selenium (as Ignas R pointed out already) OR you may wanna take a look at this tool as well: STIQ.
Best of luck!
In some cases, doing automatic testing may not be such a good idea, especially when the code base is dirty and PHP mixes it's behavior with Javascript.
It could be better to start with a simple checklist (with links, to make it faster) of the tests that should be done (manually) on the thing before each delivery.
When coding in a 3 years old minefield, better protect yourself with many error checking. The 15 minutes spent writing THE proper error message for each case will not be lost.
Use the bridging method: bridge ugly lengthy function fold() with a call to fnew() which is a wrapper around some clean classes, call both fold and fnew and compare result, log differences, throw the code into production and wait for your fishes. When doing this, always use one cycle for refactoring, anOTHER cycle for changing result (do not even fix bugs in old behavior, just bridge it).
I agree with KOHb, Selenium is a must !
Also have a look at PHPure,
Their software records the inputs and outputs from a working php website, and then automatically writes phpunit tests for functions that do not access external sources (db, files etc..).
It's not a 100% solution, but it's a great start
I do not have much experience using frameworks or anything so that leaves me with little experience using Models (MVC). I have no interest whatsoever in using a framework at the moment. I am working on a website and I am trying to model some objects but I'm not sure exactly how I should be designing the class.
For instance, right now I have a class with a few public members which can be accessed directly. I have started prototyping some functions (select, delete, update) but I am not sure
If these functions should be static
If these functions should accept parameters or use the class members instead
If these functions should even exist how they do currently
If the entire concept I'm going for is the right thing to do
I can't seem to find any sort of hints on the interwebs as to how to create a model class.
If you're using a factory class then all verbs are usually instance methods and the factory is instantiated with some sort of DB session.
If the verbs are member's of the entity's class select is usually a static method while update is usually an instance method and delete is usually defined both ways (IE: delete(recordID) and entity.delete())
The entire concept is the right thing to do but you're going to do it wrong. Period. Making a scalable model like this takes a lot more time and effort than people have at their disposal. I know you have no interest in using a framework but you should.
My inference from your question is that this is a low profile project, and you have enough flexibility from your boss/client/teacher that you can build it however you want. That in mind, here is what I would think about when working on this.
If MVC is a new concept to you, then Test-Driven Development is almost certainly and alien one as well. However, I first cracked into a real understanding of OOP while doing it, so I suggest you give it a try. Writing some simple unit tests first against your model classes will take you through the exercise of figuring out how those model classes are going to be used. You'll be working with the external API of each of those objects (or groups of objects if you're not a TDD purist), and that will help guide the design of the internals. Check out PHPUnit for getting started, as the documentation has some great examples as well.
I think the TDD approach will lead you to the following conclusions:
Probably not. Static data/methods are usually only useful when you absolutely need one copy of something. I find in web apps that aside from maybe a resource connection like the DB this is rarely the case.
This depends on what the function does. Keep in mind that using local variables implies side-effects, or changes in the state of the object. If the data you need to operate on should not change the state of the entire object, use a parameter and return a value. It's also easier to test these kinds of methods.
Again, writing tests for these functions that illustrate how you'll use them in the application will lead you to a conclusion one way or another about whether you need them or whether they are designed correctly. Don't be afraid to change them.
Absolutely. How else are you going to become comfortable with MVC if you don't roll your own implementation at least once? In fact, it's probably better to grasp the concepts with real experience before you move to a more professional framework. That way, you'll understand why the concepts and conventions of the framework are the way they are.
Oh, and the lack of clarity that you're finding on what a model class is, is probably due to the fact that it's the part of your application that is most customized. This is your data model and domain logic, so a lot of it is case-specific. The best resource, though, IMHO is Martin Fowler, whose excellent book Patterns of Enterprise Application Architecture goes into a lot of detail on how and why to design a particular set of "model" classes with one pattern or another. Here is the online pattern library--obviously the book is more detailed.
Hope that helps somewhat.
When using PHP, I think designing object oriented model adds extra work with little benefits - even when looking on large frameworks, it's common to just use assoc-arrays that you can get from resultsets (see f.ex. the multiparadigm approach of Zend MVC).
While Object-Relational mapping is much more established among strongly typed languages like Java, there are already tools for PHP as well (f.ex. Doctrine). You may check it out if having OO-oriented model is what you want, but be aware that OR-mapping has severe issues of it's own and might be of little use in PHP (haven't tried it myself in a dynamic language yet).
For most newly started project, picking a good framework is usually a way to go - it can save you time and promote best practices (of course after some learning time that's different for every tool out there). When using some framework, you should always try to find out the framework's / community approach to solving specific problems (like model design & data access) before experimenting on your own.
The "correct" way to abstract away data access using object-oriented concepts is a hot-button topic for a lot of people. Put another way, there are several ways to do it and there is no "one right" way.
Rolling your own works best if you are seriously upgrading an existing application. This is because you have a heap of code that is already database dependant and you have some bounds for the necessary refactoring. It also teaches you about abstracting code because a lot of refactoring involves removing (or reducing) code duplication. Once you've done this to completion, you will have a much better idea of how a data model layer should work. Or at least, should work for the way you program. And you will know what not to do next time you build one. :-)
If you're starting a new codebase and haven't worked with a framework or object layer but know you need to build one, then the best advice I can give is to be willing to build one later, and refactor the code to suit when that does happen. Yes, it will likely mean your application will get 90% rewritten a few times.
Writing an object abstraction layer is difficult and you will end up with dense code that is fairly defensive about things, and doesn't take chances. But once you've got it working, you will also know how to build robust code, because it will probably be debugged fairly thoroughly.
No because, static methods are hard to test
It depends of the parameter, life cycle, etc. Impossible to answer without seeing some code.
?
No
OOP requires at least 10 years of experience to have a better view on what is wrong/right/better/worse.
So, if you are not a OOP expert, instead of losing too much time reinventing the wheel, I would suggest:
Use a well-known framework for the technical part
Create your classes/framework for the business/functional part.
(1) Will help you be ready in no time for the classic technical part (Session, database interaction, etc.). Will avoid you to make errors others already did.
(2) This is your core business, it should be "your DNA".
Also, using a well-known/good technical framework will make you read quality code and help you progress. (Be carefull some frameworks are really of poor quality)
When you will have enough experience, you will be able to skip the technical framework part and build/customize your own... because technical framework are usually evil (They serve too many purposes). :)