I wish to test basic CRUD operations in CakePHP (1.3) using SimpleTest.
For example, I wish to add a new record, and make sure that I get an error message if validation fails and a new record if save goes well.
Is it better to write these tests as (1) Controller tests for the relevant action (e.g. add()), or as (2) Web Tests, using $this->post() or $this->setField()?
This is an old question but still no answer so I'll give it a shot...
I believe that the first thing you need to do is separate your concerns better. Right now what you're doing, at least to me, is a code smell...meaning something ain't right!
How did I come to this conclusion?
Well, the question you asked and how you're answering it. The question that you're asking is:
"How should I test a model's functionality?"
Your answer:
"Test it from the controller or the view"
So, the first thing I would do is setup a method in the appropriate model to do what you're wanting. Write out the code that you think you need. Save a record and return the appropriate values that you're looking for based off whatever conditional statements you come up with.
After that I'd setup some fixtures so you have some data to test against. You can learn more about CakePHP fixtures and how to create them at the CakePHP manual, http://book.cakephp.org/view/1201/Preparing-test-data (In future projects I'd make the fixtures first, but that's just a personal preference)
Once your fixtures are setup you can actually go ahead and test your new model method. Testing models, in my opinion, is the easiest to test in CakePHP. I won't go into the details here, only because the CakePHP manual, http://book.cakephp.org/view/1207/Testing-models, has a bunch of info about how to test models.
At this point you should have a properly unit tested model action and concerns properly being separated.
That being said if you're feeling super spunky and want your code tested from all angles then by all means, setup a controller test to ensure the action is performing correctly. Setup a web test to ensure the whole package is working together.
First though, separate your concerns.
Related
I am very new to TDD and am trying to create my first Djagno application with tests. I am a bit confused when it comes to generic views. I have read several places (including the official docs) that each view should have tests associated with it. But I have also read that you should avoid testing Django internals because it is unnecessary.
So if I have a view like this:
class ClinicView(DetailView):
model = Clinic
template_name = "directory/clinic.html"
which uses a generic view and works fine, should I write a test for it?
My gut feeling is that I shouldn't have to because I use a generic view but haven't really found much to tell me if my feeling is correct. What are the best practices when it comes to this? Or what would be expected of me if I was to be giving my code over to be maintained by someone else? Should I at least write a test to make sure that my model and the template exist? Thanks in advance.
You want to avoid over-testing. You should only write tests for custom logic or for things that change frequently.
For example, if the Clinic model had a complex method which calculated some result, you would want tests to ensure this does what you think it does.
If you had something that you changed often and others may come in and change, you want tests to ensure that it is still functional after your change. The Django views are already tested. Unless you add a bunch of custom logic to the View (which you should probably be putting in a ModelManager anyway) there's no point to test it repeatedly with automated tests.
Testing is great and I love it! But I hate maintaining it, so I don't aim for full coverage. Once you cover your custom code with tests, you get diminishing returns by testing every little piece.
I once worked for a company that went a little crazy and wanted me to write tests for the automated tests. Don't be like them (:
I'd like to create a highly maintainable code, with unit tests.
I have read the best practices so directories are organized as per best practice, with just one bundle named AppBundle, and I'm using annotations.
I have an issue with business logic. I've read that I should not put business logic inside controllers. As the vast majority of my code was not meant to be reused I put the logic inside the controllers. Yesterday I read here that "logic should live in the controller unless you’re going to unit test it or until you need to re-use it" and this made me faint: am I not going to unit test if I put my logic inside controllers?
I understand that "controllers should be as lean as possible, with few lines of code to glue stuff together". But what about forms? A form often has a logic like "display the form, if it's valid do something and display another page". Now if I'm going to put the form creation and logic inside a service (or a model?) I'd have to put the page render command inside that, so basically the controller would be 1 line, with all the rest inside the service, and the actual decision of which page to display would be done inside the service, not the controller itself...so what's the point of a controller, just the routing?
I really need to understand this before proceeding (i've already developed 3 months on this and I'd have to rework a lot, but better now than never)...
Thank you!
EDIT: some additional considerations to address some of the comments below.
I have a clear understanding of how forms work in Symfony, with the creation of the form and it's management with the "isValid()" in the same place.
Let's imagine the following controller which performs the following operations:
get the current customer from security context
queries the DB to get the field $user->getIsBillable()
if the user is not billable
queries the DB to find if someone else is paying for him
else //the user is billable
create and manage form1
if the user is not billable but there is someone who is paying for him
check if the license is active (I have to call an external API)
if the license is not ok
redirect to a page to update credit card info
if the user is not billable
create and manage form2
else
create and manage form3
render the license management page with all the necessary forms created
What would be supposed to do? Put all this stuff into a service which would return the forms (or null if a form is not created)? Consider that in the "is valid" of some of the forms I render the same page with simply updated info. Or should I create a service foreach of the forms creation and keep the logic in the controller?
You should keep your logic outside the controllers in order for your code to be more reusable and to reduce code duplication.
The best practice is to have your business logic registered as a Symfony service instead.
The controller should be as lean as possible as it only handles the view and accessing your services to run business logic functionality.
Using services will make your code more reusable and it will be easier to write unit tests for each part of your code.
Forms are handled in a different way in Symfony2 and you should read more about it: http://symfony.com/doc/current/book/forms.html
Like most php frameworks, symfony2 has its problems.
Turns out symfony2 best practices are not always best practices. But in most cases symfony allows for loose coupling and proper dependency injection, it just doesn't tell you in the "book".
For example a very important topic: http://symfony.com/doc/current/cookbook/controller/service.html
I usually have my form types as services, my controllers as services and other services for the business logic. My controller actions are ideally around 3-5 lines of code. Sometimes when handling a file upload they will be slightly longer though.
You can unit test your business logic services, but for your controllers and forms you will need some sort of integration testing, or use heavy mocking.
I understand that "Selenium" is a good tool for testing such things, I haven't used it yet.
One thing that I would like add to other answers provided there to you is that Unit Test is different from Functional Test.
Unit Test
You need Unit Test when you want to test individual "unit" of code (such as method in a class)
Functional Test
You need Functional Test when you want to test a "suite" of functionalities (like many methods interactions, db interactions, web services and so on)
Recap
Ideally you want to write Unit Test(s) for a class that contains heavy business logic whereas you need Functional Test(s) for testing whole controller (so a page is render with all class interactions and db ones, the page is render, the page is posted and so on)
The best approach, to me - and it's only an opinion of a devel that tried as today to understand testing from a newbie point of view - is to mix each other: with Unit Test (and isolation, of course!) I'm sure that (simplifying) every input that I provide to my method will return the correct output, while functional test will help me to test the whole thing and interactions.
Answer
So, returning to your question - that seems wider that at first look could seems - a good way to procede is to keep all business logic outside controllers (even if you're sure [and to me you'll never be sure enaugh] that code you put in will be never reused elsewhere) by defining services (as said in other answers). Then you will do some unit test(s) onto your services and after that you will probably need some Functional Test(s) to check that all "the glue keep things together correctly".
I don't know if I'm missing something (it's likely). Just to be more complete, I will attach my older question on Symfony2 (I was studying it and MVC pattern at the time)
Structuring your code to be clean and maintainable it is a very hard stuff, I suggest you to start studying the SOLID principles than having a superficial understanding of MVC:
Single Responsability Principle - SRP
Open/Closed Principle - OCP
Liskov Substitution - LSP
Interface Segregation - ISP
Dependency Inversion Principle - DIP
I'm just starting my first MVC3 application, and I'm not sure how to unit-test it. I was planning to break out helper classes (static helpers, usually) into a separate assembly, as well as model classes, so that I could test them with NUnit.
So I'm OK on helper classes; but how do I test model classes (considering that they're annotated for NHibernate and tied to the database), and how can I test my views and controllers?
What are the specific tools and techniques I need to test NHibernate-bound models, as well as ASP.NET views and controllers? I'm not sure. NUnit only solves some of the problem.
Edit: Here's some samples of code -- I'm not on my dev machine right now, so I don't have real code to show-case.
Models: Anything from the ActiveRecord documentation
Controllers: The standard HomeController from the MVC3 documentation
Views: Any strongly-typed view (let's say Create) generated from the right-click context menu (Add > View)
Specific questions:
How I can test saving models without actually saving to the main/production database
Scope for testing views; should I simply test fields exist? What about validation error messages?
Controllers: scope for testing. Should I test that actions touch and deform database data as expected (eg. /get/id gets that object; /delete/id deletes that object)?
You can get there by various kinds of tests, but you need to apply them wisely depending on what you are going to test:
Use unit test to test your controllers, or your business logic, without hitting the database.
Use integration testing by running on an in-memory database (which NHibernate supports and is easy to setup). You can make sure a scenario actually works, e.g. using a valid scenario, all the business logic is working, your controller pass the data to persistence mechanism and it goes correctly into the database.
You can use UI Testing using frameworks such as Selenium but only do that where really needed, because it is not easy as two previous types of tests, and would become hard to maintain and fragile.
It is a best practice to keep your view (UI) thin, and test other layers behind the UI, as testing the UI probably does not worth all the hassle.
I am new to unit testing. Suppose I am building a web application. How do I know what to test? All the examples that you see are some sort of basic sum function that really has no real value, or at least I've never written a function to add to inputs and then return!
So, my question...on a web application, what are the sort of things that need tested?
I know that this is a broad question but anything will be helpful. I would be interested in links or anything that gives real life examples as opposed to concept examples that don't have any real life usage.
Take a look at your code, especially the bits where you have complex logic with loops, conditionals, etc, and ask yourself: How do I know if this works?
If you need to change the complex logic to take into account other corner cases then how do you know that the changes you introduce don't break the existing cases? This is precisely what unit testing is intended to address.
So, to answer your question about how it applies to web applications: suppose you have some code that lays out the page differently depending on the browser. One of your customers refuses to upgrade from IE6 and insists that you support that. So you unit test your layout code by simulating the connection string from IE6 and checking that the layout is what you expect.
A customer tells you they've found a security hole where using a particular cookie will give you administrator access. How do you know that you've fixed the bug and it doesn't happen again? Create a unit test for it, and run the unit tests on a daily basis so that you get an early warning if it fails.
You discover a bug where users with accents in their names get corrupted in the database. Abstract out the webform input from the database layer and add unit tests to ensure that (eg) UTF8 encoded data is stored in the database correctly and can be retrieved.
You get the idea. Anywhere where part of the process has a well-defined input and output is ideal for unit testing. Anything that doesn't is ideal for refactoring until it is well defined. Take a look at projects such as WebUnit, HTMLUnit, XMLUnit, CSSUnit.
The first part of testing is to write testable applications. Separate out as much functionality as possible from the UI. Refactor into smaller methods. Learn about dependency injection, and try using that to create methods that can take simple, throw-away input that produces known (and therefor testable) results. Look at mocking tools.
Infrastructure and data layer code is easiest to test.
Look at behavior-driven testing as well as test-driven design. For my money, behavior testing is better than pure unit testing; you can follow use-cases, so that tests match against expected usage patterns.
Unit testing means testing any unit of work, the smallest units of work are methods and functions., The art of unit testing is to define tests for a function that cannot just be checked by inspection, what unit test aims at is to test every possible functional requirement of a method.
Consider for example you have a login function, then there could be following tests that you could write for failures:
1. Does the function fail on empty username and password
2. Does the function fail on the correct username but the wrong password
3. Does the function fail on the correct password but the wrong username
The you would also write tests that the function would pass:
1. Does the function pass on correct username and password
This is just a basic example but this is what unit testing attempts to achieve, testing out things that may have been overlooked during development.
Then there is a purist approach too where a developer is first supposed to write tests and then the code to pass those tests (aka test driven development).
Resources:
http://devzone.zend.com/article/2772
http://www.ibm.com/developerworks/library/j-mocktest.html
If you're new to TDD, may I suggest a quick trip into the world of BDD? My experience is that the language really helps people pick up TDD more quickly. Particularly, I point you at this article, in which Dan North suggests "what to test":
http://blog.dannorth.net/introducing-bdd/
Note for transparency: I may be heavily involved in the BDD movement.
Regarding the classes to unit test in a web-app, I'd consider starting with controllers, domain objects if they have complex behaviour, and anything called "service", "manager", "helper" or "util". Please also try renaming any classes like this so that they are less generic and actually say what they do. Classes called "calculator" or "converter" are also good candidates, and you'll probably find more in the same package / folder.
There are a couple of good books which could help you too:
Martin Fowler, "Refactoring"
Michael Feathers, "Working Effectively with Legacy Code"
Good luck!
If you start out saying, "How do I test my web app?" that is biting off a lot at once, and it's going to be hard to see unit testing as providing any kind of benefit. I got into unit testing by starting with small pieces that were isolated, then writing libraries test-first, and only then building whole applications that were testable.
Generally a web app has a domain model, it has data access objects that do queries on a database and return domain objects, it has services that call the data access objects, and it has controllers that accept http requests and call the services.
Tests for the controllers will check that they call the right service method with the right parameters. Service objects can be mocks injected during test setup.
Tests for the services will check that they call the right data access objects and perform whatever logic they need to be performing. Data access objects can be mocks injected during test setup.
Tests for the data access objects will check that they perform the right database operation (query or update or whatever) by checking the contents of the database before and after. For dao tests you'll need a database, and a tool like DBUnit to pre-populate it before the test. Also your domain objects' getters and setters will get exercised with this test so you won't need a separate test for them.
Tests for the domain model will check that whatever domain logic you have encoded in them works (Sometimes you may not have any). If you design your domain model so it is not coupled to the database then the more logic you put in the domain model the better because it's easy to test. You shouldn't need any mocks for these tests.
For a web app the kind of tests you need to do are slightly different. Unit tests are tests which test a particular component of your program. For a web app, you would need to test that forms accept/reject the right inputs, that all links point to the right place, that it can cope with unexpected inputs etc. I'd have a look at Selenium if I were you, I've used it extensively in testing a number of sites: Selenium HQ
I don't have experience of testing web apps, but speaking generally: you unit test the smallest 'chunks' of your program possible. That means you test each function on an individual basis. Anything on a larger scale becomes an integration test.
Of course, there are going to be methods so simple that its not worth your time to write a test for them, but on the whole aim to test as great a proportion of your code as possible.
A rule of thumb is that if it is not worth testing it is not worth writing.
However, some things are very difficult to test, so you have the do some cost benefit analysis on what you test. If you initially aim for 70% code coverage, you will be on the right track.
If I'm having Data Access Layer (nHibernate) for example a class called UserProvider
and a Business Logic class UserBl, should I both test their methods SaveUser or GetUserById, or any other public method in DA layer which is called from BL layer. Is this a redundancy or a common practice to do?
Is it common to unit test DA layer, or that belongs to Integration test domain?
Is it better to have test database, or create database data during test?
Any help is appreciated.
There's no right answer to this, it really depends. Some people (e.g Roy Osherove) say you should only test code which has conditional logic (IF statements etc), which may or may not include your DAL. Some people (often those doing TDD) will say you should test everything, including the DAL, and aim for 100% code coverage.
Personally I only test it if it has logic in, so end up with some DAL methods tested and some not. Most of the time you just end up checking that your BL calls your DAL, which has some merit but I don't find necessary. I think it makes more sense to have integration tests which cover the app end-to-end, including the database, which covers things like GetUserById.
Either way, and you probably know this already, but make sure your unit tests don't touch an actual database. (No problem doing this, but that's an integration test not a unit test, as it takes a lot longer and involves complex setup, and should be run separately).
It is a good practice to write unit test for every layer, even the DAL.
I don't think running tests on the real db is a good idea, you might ruin important data. We used to set up a copy of the db for tests with just enough data in it to run tests on.
In our test project we had a special web.config file with test settings, like a ConnectionString to our test db.
In my experience it was helpful to test each layer on its own. Integrating it and test again. Integration test normally does not test all aspects. Sometimes if the Data Access Layer (I don't know nHibernate) is generated code or sort of generic code it looks like overkill. But I have seen it more than once that systematic testing pays off.
Is it redundancy? In my opinion it is not.
Is it common practice? Hard to tell. I would say no. I have seen it in some projects but not in all projects I worked in. Was often dependend on time/resources and mentality of the team / individiual developer.
Is it better to have test database, or create database data during test? This is quite a different question. Cannot be answered easily. Depends on your project. Create a new one is good but sometimes throws up unreal bugs (although bugs). It is depending on your project (product development or a proprietary development). Usually in an proprietary on site development a database gets migrated into from somewhere. So a second test is definitely needed with the migrated data. But this is rather at a system test level.
Unit testing the DAL is worth it as mentioned if there is logic in there, for example if using the same StoredProc for insert & update its worth knowing that an insert works, a subsequent call updates the previous and a select returns it and not a list. In your case SaveUser method probably inserts first time around and subsequently updates, its nice to know that this is whats being done at unit test stage.
If you're using a framework like iBatis or Hibernate where you can implement typehandlers its worth confirming that the handlers handle values in a way that's acceptable to your underlying DB.
As for testing against an actual DB if you use a framework like Spring you can avail of the supported database unit test classes with auto rollback of transactions so you run your tests and the DB is unaffected afterwards. See here for information. Others probably offer similiar support.