Learning Yii Testing - Sample Chapter
Learning Yii Testing - Sample Chapter
Learning Yii Testing - Sample Chapter
ee
P U B L I S H I N G
C o m m u n i t y
E x p e r i e n c e
D i s t i l l e d
$ 36.99 US
24.99 UK
pl
Matteo Pescarin
Sa
m
Matteo Pescarin
[1]
This chapter has been divided into the following three sections:
[2]
Chapter 1
Atlassian's QA team lead Penny Wyatt points out that teams where quality assurance
was not performed or left alone to perform small automation tasks, with unit tests
for instance, had the highest story rejection rate, which is when a story will have
to be re-opened after being completed because of wrong or missing functionality.
We are talking about a 100 percent of rejection rate.
When such a situation occurs, we are left in a state where we have to go back into
development and fix what we've done. This is not the only case: together with it, late
discovered bugs and defects, and fixing them, are possibly some of the most expensive
tasks in software development. In most cases, it has been shown that their cost is also
way higher than it would have been to prevent them in the first place. Unfortunately,
software development is rarely devoid of defects, and this should always be kept
in mind.
As developers and managers, one of the goals we should have is to reduce the
occurrence of defects to an economically acceptable level, and doing this also
reduces the resulting risk associated with it.
As a practical example, a large website might have thousands of software errors
but still be economically viable due to the fact that 99 percent of the website is
displayed correctly. For a Falcon rocket or a Formula 1 car, a defect rate that high
is not acceptable: the risk of having a single one in the wrong place might also cost
the lives of people.
The other implicit aim for defect reduction is an investment in teamwork. An error
introduced by one developer can have a ripple effect on the work of other team
members and, overall, trust in the code base and other colleagues' work. In this
chapter, and the later chapters, we are going to discuss this aspect in more detail
by introducing some concepts of project management and how it can cooperate in
ensuring that quality is ensured on many levels.
The last and possibly an equally important aspect is how testing can be used to
document the code by example. This is rarely discussed or brought to the attention
of developers, but we will see how tests can describe the functionality of our
implementations in a way more precise manner than what PHP documentation
comments can provide. I'm not saying documentation comments are useless, quite the
contrary: in modern integrated development environments (IDE) such as NetBeans
or PHPStorm, auto-completion and code hinting are a great way to improve the time
to discover the underlying framework without having the need to search through
a reference manual. Tests can and should in fact provide the much needed help a
developer might need when trying to combine and use yet unknown interfaces.
[3]
When working with open source software that is a result of the work of a small
self-organized team, having the ability to provide documentation without an
extensive effort might be the key to rapid and continuous delivery.
But how do we ensure a delivery can be met within constraints that are imposed
on the team? In order to explain this, we will have to take a quick detour into
project management, from where some of the practices that are discussed and
used in this book have been originating.
Time
Quality
Cost
One of the agile methodologies that are nowadays not particularly talked about,
Extreme Programming (XP), has introduced, if not rather exposed, a new variable
into the equation: scope.
[4]
Chapter 1
From the XP point of view, after the breakdown phase, we will have to go through a
phase of estimating each single task, and based on the budget, you just keep adding
or removing tasks.
This discussion brings up a problem that is currently widely discussed in the
community, as estimating tasks is not as easy one might think. We'll dive into it
shortly, as I've seen too many misunderstandings of this topic.
Estimating tasks
As we've seen, estimation of the tasks has always been considered one of the
fundamental principles of how the delivery path of a project is scheduled. This is
especially valid in agile methodologies, as they use fixed time iterations and compute
the amount of features and tasks that can be fitted in the given sprint and adjusted
at each iteration using tools such as the burn down chart.
If you've worked in agile environments, this should be pretty
much easy to understand, and if you haven't, then there's plenty
of information that can be gained by reading books or articles on
SCRUM that are freely available online.
Unfortunately, with all the importance estimation has, it seems like nobody
really looked deeper into it: there are plenty of articles that warn how much
software development task estimations are always off by a factor of 2 or 3. So,
should we just swallow the fact that we won't get better at estimating or is there
something more to it?
The "estimations do not work" argument is probably not correct either, and recently
the hashtag #NoEstimates has sparked a bit of discussion online, which is probably
worth including here.
As a matter of fact, estimations do work. The only detail that is normally overlooked
is that the estimation is nearing the actual time spent on it depending on how much
knowledge the developer has and how much controllable the environment is.
[5]
In fact, the reality is twofold: from one side, we will get better at estimating the
greater our experience is, and, on the other side, our estimation will be closer to
reality if there are less unknowns in our path.
This is well-known in project management as the Cone of Uncertainty.
What we really need to do is admit and expose all the aspects that would increase
the risk and the uncertainty of our estimations, while trying to isolate what we
know is going to take a specific amount of time.
As an example, having a fixed time investigation period to create working
prototypes of the features we are going to implement sets a precedent for future
computations, while human factors will need to be factored in.
While estimations are particularly important from the business perspective of
software development and project management, we won't be touching them again in
this book. I'd rather focus on more practical aspects of the development work flow.
Testing approaches
Extreme Programming tries to stress the investment in defect reduction.
In order to do so, it introduces two basic principles: double-checking and
Defect Cost Increase (DCI).
Double-checking is software testing. We know how a particular feature should be
working, which can be represented through a test. When implementing such a feature,
we know in a quasi-deterministic way that what we've done is actually correct.
Extreme Programming makes use of values, principles, and practices to
outline the core structure of the methodology: in short, you pick values
that describe you as a team; you adhere to certain principles that will
lead you into using specific practices.
Principles can be considered the bridge between values and practices,
justifying the use of practices on something more concrete than a mere
"but everybody's using it."
The other principle of DCI can be used to increase the cost-effectiveness of testing.
What DCI states is the following:
"The sooner you find a defect, the cheaper it is to fix."
Kent Beck
[6]
Chapter 1
To make this even more clearer with an example, if you find a defect after years
of development, it could take a lot of time to investigate both what the code was
originally meant to be doing and what was the context it was developed in the first
place. If, instead, you find the defect the minute it's being implemented, the cost
to fix it will be minimal. This, clearly, doesn't even take into consideration all the
hidden costs and risks that a severe bug can cause to critical sections of our code
base; think about security and privacy for instance.
Not only the longer we wait the more difficult the defects will be to be amended, but
also their cost will increase and have the potential to leave many residual defects.
This means that by adhering to DCI, firstly, we need to have shorter feedback cycles
so that we can continuously find as many defects as possible, and, secondly, we
will have to adopt different practices that can help us keep the cost and the quality
untouched as much as we can.
The idea of finding defects rapidly and often has been formalized as Continuous
Integration (CI) and requires bringing automated testing into play to avoid the
costs spiraling out of control. This practice has gained a lot of momentum outside
XP and it's currently used widely in many organizations regardless of the project
management methodology adopted. We will see how CI and automation can
be introduced in our work flow and development in more detail in Chapter 9,
Eliminating Stress with the Help of Automation.
These practices defy entirely the idea of working in a waterfall way, as shown in the
following figure:
[7]
Since the advent of agile methodologies, which XP is part of, there has been a great
effort to bring testing as early as possible.
Remember that testing is as important as development, so it should be quite clear
that we need to treat it as a first-class citizen.
One of the common situations you might find yourself in is that even if you start
testing right at the beginning while the code base is being developed, it could
potentially raise more issues than those that are needed or can be addressed. The
resulting situation will still generate a good amount of problems and technical debt
that won't fit within the delivery path, as you can see in the following figure:
[8]
Chapter 1
The team's goal is to eliminate all post-development testing and shift testing
resources to the beginning. If you have forms of testing such as stress or load testing
that highlight defects at the end of the development, try to bring them into the
development cycle. Try to run these tests continuously and automatically.
Transitioning into a work flow that has testing at the beginning brings to the surface
two main problems: the accumulation of technical debt and the inherent problem
that developers and testers are considered two separate entities. Don't forget that
there will be still some testing that will happen after development and will clearly
need to be performed by third parties, but, nonetheless, let's stress the fact that our
efforts are to reduce it as much as we can.
As I'll constantly remind you, testing is not someone else's problem. Instead, with
this book I'm aiming at giving the developers all the tools that can make him/her a
tester first. There are different approaches to this problem, and we'll address them
shortly at the end of this chapter, when talking about the testing mentality.
Unfortunately, TDD tries to focus on the atomic part of the features being developed,
and it fails to give a broader vision of everything, of what has been tested and how
much, or, even better, if what has been tested is of any relevance for the business and
the product itself.
Once again, XP, in order to gain the full benefits of double-checking, introduces the
following two sets of tests:
In the first case, it allows the programmers to test all the system's components
exhaustively, and in the latter case, the operation of the system as a whole.
The latter can in a way be seen as what Behavior Driven Development (BDD)
describes in a more formal way. We're going to cover BDD in more detail in
Chapter 2, Tooling up for Testing.
BDD tries to cover TDD's lack of overall scope and shifts the attention to the
behavioral aspect of the project. BDD is effectively an evolution of TDD but
requires some changes in the organization of the work and the way it's shipped,
which can be quite difficult to introduce in some environments without re-assessing
the whole workflow.
With BDD, you define what to test and how to test it on multiple levels, detailing the
scope of testing using a well-defined, business-oriented language called ubiquitous
language, borrowed by Domain-driven Design (DDD) that is shared among all
members of the team, both technical and non-technical. For the scope of this chapter,
it should suffice to say that BDD introduces the concept of stories and scenarios
giving the developer the ability to formally describe the user perspective and
functionality of your application. Tests should be written using the standard agile
framework of a user story: "As a [role] I want [feature] so that [benefit]." Acceptance
criteria should be written in terms of scenarios and implemented as classes: "Given
[initial context], when [event occurs], then [ensure some outcomes]."
[ 10 ]
Chapter 1
Planning tests
Planning is, hence, critical when stepping into testing from a software development
point of view, and in not-so-recent years, there have been several solutions to
improve testing from a planning perspective that give a more detailed and compact
way to define the so-called test plan.
In a testing-oriented environment, test plans should give you the direction and
the indications of what and how much to test at any level. Moreover, the test plan
is something that should be exposed to the various stakeholders and its visibility
shouldn't live within the walls of development. Due to this, it's our responsibility
to maintain and let this document live throughout the life of the project.
In practice, I've seen this rarely happening because test plans are never formalized
or, if they are, they are too long and hard to maintain, suffering from a very short
lifespan since their initial conception.
As an example, Attributes-Components-Capabilities (ACC) has been created by
Google in order to solve some of the main problems that test plans have always
suffered, especially their maintainability. You can find more information about
ACC and Google Test Analytics software at https://code.google.com/p/testanalytics/.
ACC test plans are short and compact, and the whole project tries to aim to test
plans that could be created in minutes and that are self-describing and valuable
to anyone close to the project.
For each component, you have a series of capabilities, which can be described with
one or more attributes; think, for instance, "secure", "fast", or "user-friendly". On top
of this, each capability and component has a relative risk level associated with it.
These two things together allow you to understand what is most important to test
and how thorough your testing should be.
Generating tests
Clearly, planning tests is just the beginning. Once you get into the implementation
side, you can pick up this book, which provides the knowledge of how to use the
tools available to create tests.
There isn't much more I can tell you about this aspect. You probably just need to
read it all, but it should be stressed that there are some basic principles you must
keep in mind when writing tests.
[ 11 ]
Simplicity: Test only one thing. The smaller the test the more
controllable it is.
Once you've got a grip of how to approach a project, viewing it from the architectural
point of view, and once you've understood how test plans work and what you really
need to test, you can start implementing tests, discuss them, and improve
the tools and the way you're using them with the help of your colleagues.
[ 12 ]
Chapter 1
The knowledge part comes from a higher view of the product, both from the
technical side and the business end. Introducing project breakdowns and pitches
for the features that are going to be introduced in our software can be a starting
point in this process.
The quality mindset can be the trickiest of them all, as it ends up being baked into
all sort of aspects of software development from the technical point of view and
requires a proactive participation from all the parties involved, first of all starting
with the developer.
As previously said, there isn't a fixed definition of what you can achieve in terms of
quality. There's no upper limit on how much quality you can put into your project.
Hence, there's no limit on how much testing you can do in any project.
From what I've witnessed, there are two requirements that can speed up the process
of becoming a good tester on top of being a good developer: one of these comes from
the environment, the other comes from us.
The environment bit in my opinion is the one that could potentially cut the deal to
acquire the right testing mindset that we are talking about, and getting there should
probably be the priority of any company that decides that quality has value, and a
measurable one.
Surely, having someone that can do mentoring on testing has always worked the
best: learning by imitation and debating are probably the best team-oriented tools
around. Even if you don't have a tester in your team, you might have noticed that in
development, practices such as paired programming or code reviews can go a long
way to keep the team up to speed with the practices and knowledge required.
Let's have a closer look at what this would mean in practice, keeping in mind that
there is no silver bullet in terms of applied practices and methodologies, and it's
your task to experiment and adapt based on what you have at hand.
[ 13 ]
First of all, you need support from the business and your direct managers; speaking
of direct and indirect experience, without that you won't get anywhere. The business
side of the company needs to understand what testing is, in the way that is has been
described at the beginning of this chapter, the value of testing, and all the good
things that this can bring. There is plenty of documentation online for you to build
a business case.
Secondly, you need to have some skillsets in testing. This book should cover that
parthopefully quite welland there are plenty of others that can teach you more
theoretical aspects of testing for programmers and engineers, without considering
the amount of online resources available on the topic.
A few good articles you can find online are as follows:
Once you've got this, you can start moving into action.
One of the situations most might find themselves in is that there is no testing culture
whatsoever. Here you have two choices: either take the bottom-up approach, and get
yourself familiar with TDD as a starter, or take the top-down one, where you'll take
the higher perspective.
Either way you need to start having a compact test plan to adhere to. Taking as an
example the approach of ACC, you start by breaking down the application/project/
library into modules (components), each of them will be composed of features
(capabilities). Each feature will be denoted with a particular attribute. From there
you should have a compact enough representation of what you're trying to achieve.
On top of this, you can start assigning a relative risk level, which you will use to
give priority for your testing approach defining what and how much to test.
[ 14 ]
Chapter 1
The resulting test plan should be signed off by all the stakeholders and updated as
frequently as possible, defining the aim of the project itself. The more this document
is official the better it is, as it will be considered the business card of the project.
As highlighted by many, the immediate aim is to start planting the culture of
testing in developers. Define the scope of your work, both in terms of testing and
development, proceed with caution and evaluate both risks and costs, and leverage
on those to take a decision on how to approach tests.
Thankfully, if you're finding yourself working with Yii and Codeception, you
should be spared a bit of headaches putting together different frameworks and
wasting a bit of time experimenting a working solution.
Team-wise, when the experience in testing is not widespread nor solid, additional
practices can be introduced that can help avoid bottlenecks or have all the knowledge
trapped in a single person, such as paired programming and code reviews.
Some companies, like Atlassian, introduced test engineers that could help the
teams, both from a mentoring perspective and a mere quality assurance side. Their
interventions in the development cycle ended up being confined to a more restricted
participation, at the very beginning and before completing the task. Their role is,
nonetheless, fundamental, as they became the guardians of the testing infrastructure,
the tools, and the practices to be adopted, while the developer grew to become a fully
fledged tester who can cover almost any aspect of testing without much support.
Summary
In this chapter, we've covered many aspects that are directly connected with testing,
but are not strictly necessary to start testing, although they are fundamental if
you want to understand why you've taken up this book and if it's necessary to go
through the rest of it.
You've seen why it's important to test, some project management methodologies,
how to estimate tasks and what it entails, and you've seen different testing
approaches such as TDD and BDD, which will be the basis for many of the remaining
chapters. At the end, I've tried to give an idea of what it takes to gain the testing
mindset required to become a master in this art.
In Chapter 2, Tooling up for Testing, we will start gearing up with the tools we are
going to use throughout the rest of this book, understanding the basics of Yii 2
and applying what we've learned in this chapter by outlining our test plan.
[ 15 ]
www.PacktPub.com
Stay Connected: