Esta é a segunda parte de uma série sobre Fora-in Development Comportamento Impulsionada em PHP. A primeira parte introduz de fora para dentro, desenvolvimento e como executar cenários com Behat. Leia este para apanhar com as ferramentas eo exemplo que temos utilizado até agora, e depois voltar para descobrir como PHPSpec se encaixa nesse quadro.
PHPSpec é o primeiro framework PHP BDD. É um porto de RSpec para PHP criado em 2007 por Pádraic Brady e Swicegood Travis. Desenvolvimento, neste quadro parado por um tempo e foi reacendido agosto do ano passado (2010). PHPSpec pode ser instalado via pear, usando estes comandos:
PHPSpec é o primeiro framework PHP BDD. É um porto de RSpec para PHP criado em 2007 por Pádraic Brady e Swicegood Travis. Desenvolvimento, neste quadro parado por um tempo e foi reacendido agosto do ano passado (2010). PHPSpec pode ser instalado via pear, usando estes comandos:
Se você está acostumado a testes unitários, aqui é uma folha de tradução rápida para xUnit / xSpec termos:
- Em xUnit nós teste , em xSpec que descrevem , de modo os seus nomes de classe começam com "Descrever"
- Em PHPSpec, o arquivo spec para uma classe MyClass é nomeado MyClassSpec.php
- Em testes xUnit nós grupo em um TestCase . Em xSpec temos exemplos que são agrupados em Contextos
- Em xUnit cada método é um teste com o prefixo de teste . Em xSpec cada método é um exemplo , usamos o prefixo que
- Em xUnit que afirmam que o trabalho algo tão esperado. Em xSpec que especificar como ele deve trabalhar
Nós usamos Gherkin e Behat para especificar como a nossa aplicação é suposto para trabalhar. Usamos PHPSpec para especificar o comportamento de nossas aulas. Para começar, vamos ver um exemplo simples mostrando isso. Estamos construindo uma classe que cumprimenta o usuário com "Olá, Mundo!". O
GreeterSpec.php
arquivo ficaria assim:
If you already have experience with Unit Testing, the above would look familiar to you. Note that instead of saying:
$this->assertEquals('Hello, World!', $message)
we say $message->should->be('Hello, World!')
. We are describing how we want the behaviour to be, rather than testing it. The before()
method is a setup method that would get run before any example is run; the spec()
method is a decorator that wraps the object being tested so we call the expectations on the properties and methods results.
To run the spec we use the phpspec command:
First we run it and watch it fail. Then we write a Greeter class to satisfy the example.
PHPSpec and MVC
Going back to our Video Renting application. The newly released version (1.2beta) includes integration with Zend Framework which enables us to test the MVC (Model, View, Controller) components individually. When we test an MVC application, we should start with the view, because that’s what our scenario describes:
The text “Revolution OS” was not found anywhere in the text of the current page
Let’s keep all our specs in a folder called “spec”. To write a view spec we first add a folder called views under the spec folder. In our example, this is a view that corresponds to the index action of the review controller. We need to create an
IndexSpec.php
for our index.phtml
view, containing the following code:
Notice that we namespaced our class with the name of the controller. In a modular Zend Framework application you would namespace with the module name and then controller name, e.g.
Module\Controller
.
If we run the spec we should see an error because we haven’t met its description yet.
At this stage we need to create the view to deal with the error we saw. In this example, we will use Zend Tool, which creates the controller/action/view all in one go:
Now instead of an error, our output shows that we have a failure:
This output means that the view now exists, but it’s not showing the described text. That’s what we expect, since we haven’t coded the view yet. Let’s add some code to do so:
It should now pass.
That’s progress! However Behat is still not happy, because our controller is not setting the model for the view yet. Let us turn our focus to the controller, and start by creating a
controllers
directory and adding a ReviewControllerSpec.php
.DescribeReviewController
must extend \PHPSpec\Context\Zend\Controller
. We also need to specify that our controller will send be accessed by POST and will create the model in it. The controller/action will be routed from “/review” and we can add an example to make sure the route work as expected.
We’ll also want to add the code for the controller itself. Assuming you are using Yadif or another IoC (Inversion of Control) container, it would look like this:
We’ll see that this now passes, when we run:
This looks much healthier, but if we run Behat, it will still be unhappy. We need to pass real data to the view, and then Behat will point out that the next step now is to describe the model. We need to have the data of our selected movies so we can fetch our view properly. Testing the models should be focused on behaviour, rather than the mechanics of database access. We know Zend_Db works, we need to know if we have made mistakes in our model. We will therefore test for the validation, filtering and business rules that we keep in the model.
We need to implement a
isValid()
method in the Video
model. PHPSpec does not have a beValid
matcher, but it will use predicate matchers and find a method isValid()
by magic. Once the isValid()
is implemented properly than the spec passes. You can do something similar if the form validation is stored in your (zend) forms. Also note the before()
method that will be called before any example is run.
You can describe your mapper’s behaviour by inspecting that it calls the Data Access Object (DAO) to fetch to or persist data from the models. At that point you can then add the DAO (e.g. DbTable, Rss, etc).
Should we Hit the Database?
In many cases you simply need to verify the business logic and not the database operation. Hitting the database consumes both time and resources, which will slow down the execution. There will be times where we need to expose some database behaviour or just feel more confident that our models work. In those cases we can use a Test Data Builder pattern (this is a topic on its own, and I will save it for another post).
If you run Behat again after the model specs pass, the view should be displaying the correct data, so your scenario should pass, and a new scenario will be failing. We use Behat to tell us what to do next, and so the outside-in cycle is begins again.
Final Thoughts
In BDD, developers are driven by the specification, rather than tests of things they haven’t written yet. That said, the goals of both TDD and BDD are basically the same: making sure the user gets what they want. BDD makes that focus more explicit, and uses a language that invites the user to write their tests as a specification.
Behat and PHPSpec sit at different levels in the Outside-in cycle. Behat provides the outermost layer, allowing the stakeholders and developers to collaborate. PHPSpec provides the inner layer, allowing the specification of how the classes will collaborate with each other.
Nenhum comentário :
Postar um comentário