The first chapter is a relatively long and unnecessary introduction to OOP, ECMA5 and polyfills. It goes on talking about coding style, against using magic-constants, etc. Skip to the 2nd chapter.
Second chapter is an introduction to Jasmine. If you are not familiar with Jasmine, I suggest reading the interactive documentation instead http://jasmine.github.io/2.0/introduction.html.
Chapters 2.2, 2.3 introduces concepts of the baby steps and Red-Green-Refactor.
- Tight feedback loop
- using "baby steps" in development, switching a lot between code and test cases, i.e. less scanning of the code.
The single most important metric of BDD is binary one (Red-Green-Refactor):
- are all specs green (after the implementation phase)?
- is one spec red (after coding another spec)?
The next term that you need to know is Triangulation.
- instead of filling in a real implementation, you can fake it with a dummy value. You know that your implementation isn't ready, but all the specs are showing green. This implies that there is a spec example missing.
By now, you know that BDD is:
- Spec/Error driven coding.
- Using baby-steps to achieve a "tight feedback-loop".
- Follow the Red-Green-Refactor (RGR) cycle to avoid the false-positives.
RGR cycle enhances the separation of the workload. Red is for the interface, green is for the implementation.
- Specs enables code refactoring.
- Specs should be readable (DAMP over DRY).
- altering internal code structure without affecting the external behaviour.
- Descriptive and Meaningful Phrases.
Use Example Factory to generate the SUT (Subject Under Test). Follow the SEE pattern to maintain the specs readable.
- Example Factory
- a factory method used to instantiate the SUT object with canonical values, overwriting only the properties relevant to the test case (e.g., https://gist.github.com/gajus/d75de7f3fdbfd6486d6a). See https://github.com/petejkim/factory-lady, Object Mother and Test Data Builders.
- SEE pattern
- (Setup, e.g. create an object; Execute, i.e. introducing change to the object state; Expect, i.e. state an expectation of what should have happened). The spec must implement not more than one execution. The spec must abstain from several expectations. Do not use if-statement that lead to multiple execution and expectation branches – write several specs instead.
The specs are organised either per Feature (topic, https://gist.github.com/gajus/2a7fd107f897213aee67) or per Fixture (example data, e.g. https://gist.github.com/gajus/c93f8bac2fe402881916).
Talks about the benefits of the automated specs over the written documentation. In essence, as these tests are executable they always have to match the real product (thus cannot get out of date). Furthermore, this form of documentation is comprehensible to all three groups involved in the product development: testers, programmers and business people.
Explains the difference between the outside-in and inside-out development. The latter means that you start with the basic components that make up the application (e.g. https://gist.github.com/gajus/87acb66a7823c2d71c05). The former – you start with the implementation of the specs that have meaning to the business using hypothetical components (aka. acceptance test, e.g. https://gist.github.com/gajus/32a61ea65183c4584682). The upside of the outside-in development is that you never write code that will become redundant (the requirement can be traced back to the spec). The downside is that you cannot run the test cases until the implementation is complete.
- Acceptance test (or customer test)
- high level specs describe a scenario from the view of an application user. In contrast to the low level spec, a high level spec does not have an SUT.
High level spec:
- they help to become aware of bugs – all spec violations are considered a bug (defect awareness)
- they are most useful when shown to stakeholders
- there are usually only a few. they don't include all special cases. their main purpose is to provide an overview of the required functionality.
Low level spec:
- they help to find specific bugs (localization)
- they are most useful to the developers who maintain the code later
- there are usually a lot of low level specs since they need to cover all the low level details, special and edge cases
BDD project usually starts with writing the outer circle (high level specs) and then proceeding the implementation of the inner circle (low level specs).
Chapter 6.3, 7
Introduction to the dummies (empty object that does nothing), stubs (method designed just for testing), mocks (object designed just for testing) also Jasmine test double functions called spies (http://jasmine.github.io/2.0/introduction.html#section-Spies).
Chapter 8, What is BDD?
In this chapter, the author quotes various definitions of BDD. The ones that make the most sense to me are:
Developers pull features from stakeholders and develop them outside-in. The features are pulled in the order of their business value. The most important feature is implemented first and it's implemented outside in. No time is wasted building unnecessary code.
The evolution of a programmer that is learning TDD is a good guidance in understanding the BDD.
- Most developers start by writing unit tests to existing code.
- After some practise they learn about the advantages of writing the test first. They might learn about good testing practices like AAA, stubs and factories at this point.
- They realise that TDD can be used as a design tool to discover the API of the production code.
- Eventually they recognise that TDD is not about testing. It's about defining behavior and writing specifications that serve as living documentation. They also discover mocks and outside-in development.