By the end of this lesson, students should be able to:
- Develop a Rails API using outside-in, behavior-driven testing.
- Describe the difference between Behavior and Test Driven Development (BDD vs TDD)
- Drive behavior specification with user stories.
- Write automated CRUD request specs with RSpec.
- Drive routing, model, and controller specs using request specs.
- Write model unit specs for associations and validations.
Unit Test: A test written to check for correct behavior of the smallest possible piece of code, most often a function, method, or procedure. Unit tests should not care about or involving integrations such as HTTP requests or Databases, global variables, other units of code, or UI. It should only care about simple input arguments and the expected results.
Feature Test: A test written to check for correct behavior at the level of a feature / module which involve multiple units working correctly, sometimes testing integrations across services, which involve multiple features working together. These features have behavior meeting one or more user stories. Feature testing should not care about UI.
UI Test: A test written to check for correct behavior / presentation of the UI. UI Tests often require one of more features to work correctly.
Non-Functional Test: A test written to check for non-functional aspects of an application, such as performance, scalability, interoperability, reliability etc.
Test Driven Development: Where a test is written to first describe the behavior of a feature or unit, and the test will initially fail as the code to provide the behavior has not been written yet. Then, you implement the code to pass the test, possibly re-factoring the code later for better code style / elegance and re-test.
Behavior Driven Development: The idea that you want to be testing the behavior of the feature, or unit, not the implementation details. If you are testing too close to the implementation, the test will fail when the overall behavior is still correct, because your test is tied too closely to implementation, making changes "under-the-hood" cause the test to fail.
Bug Driven Development: Simply fixing bugs as they come up when running your code. This can fix small issues as they come up, but you have no way of knowing if your fixes really fix all possible behaviors of a unit, feature, or integration and also, your fixes could silently break other piece of code.
Top-Down Testing: Testing by first passing test for the highest level of organization in the code (modules / features ) and making them pass, often building "stubs" for lower level units that have the correct behavior to pass the test but are not finished implementations of the unit code.
Bottom-Up Testing: Testing by first building units that pass the tests, then combining units into modules / features that then pass the test.
Stub: A small piece of code written to simulate a unit's correct behavior under a narrow subset of that unit's expected inputs. Written to make top-down testing work before a unit can be fully implemented correctly.
Test Coverage: How much of your codebase's behavior that can be tested using tests, usually described using a percentage.
Regression: Changes to your codebase that make previously working units, features / modules, or integrations stop working. When you make changes to your codebase, running tests after every significant change can check if you have an regressions.
Testing Framework: A language-specific framework that provides an easily readable API for writing tests. Sometimes different classes of tests are done using different testing frameworks.
Behavior vs Implementation: Behavior is the high level expectation of how a unit, feature, or integrations works, where the "under-the-hood" code that makes it work does not matter. IE, if it works, it works, an the code itself is a "black box" that simply takes inputs and produces the appropriate output. Implementation is the actual code "under-the-hood" that produces the behavior. Implementation can vary from revision to revision when re-factoring code, but the overall behavior of a unit, feature, or integration should remain the same.
Backfilling: Writing tests for your codebase after you've already written the code. This is less preffered that Test Driven Development because it's more likely your code is disorganized if you didn't write tests first, and also, it can be hard to get nearly-complete test coverage when you've been focusing so much on implementation that it's not clear what behaviors you need to write tests for.
- coming after lesson!
// code goes here