Test Driven Development: A Change in People’s Mindset

Kezia Irene Tesiman
LEARNFAZZ
Published in
5 min readFeb 27, 2019

Test-driven development is a software development process that creates software in very short iterations with a minimal upfront design. Poised for widespread adoption, TDD has become the focus of an increasing number of researchers and developers.” — Janzen, D., & Saiedian, H. (2005).

Test-driven development has emerged in conjunction with the rise of agile process models. Both have roots in the iterative, incremental, and evolutionary process models used as early as the 1950s. In addition, tools have evolved to play a significant role in supporting TDD. The practice involves the implementation of a system starting from the unit test cases of an object. Writing test cases and implementing objects, methods triggers the need for other objects/methods. An important rule in TDD is: “If you can’t write a test for what you are about to code, then you should not even be thinking about coding ”

Test-driven Development method is chosen to help the developers to think more thoroughly about the requirements of their story. The developers have to think about the input and output that is required and then they have to make a unit test before writing any actual code. This method is intended to make the developers do not rush to write the code, instead to think of the code more as a structure. If this method is implemented, it will help the developers to follow the software engineering quality standard.

This method will also help to prevent errors in the future. Because even if the code is modified and there are errors on the modified code, the error will be much easier to detect because of the unit test that has been written before the actual writing of the working code.

What exactly is Test Driven Development?

According to George, B., & Williams, L. (2004), Test Driven Development starts with thoughts on how to test the required functionality. After writing automated test cases that generally will not even compile, the programmers write implementation code to pass these test cases. The work is kept within the programmer’s intellectual control; as the programmer is continuously making small implementation decisions and increasing functionality at a relatively consistent rate.

All of the test cases that exist for the entire program must successfully pass before new code is considered fully implemented. Hence it is perceived, with a degree of confidence, that the new code will not introduce a fault or mask a fault in the current code base. Another thumb rule in TDD is that whenever a software defect is found, unit test cases are added to the test suite prior to fixing the code.

Benefits of Test Driven Development

According to George, B., & Williams, L. (2004), these are the benefits of implementing Test Driven Development:

  1. Program Comprehension: According to T.A. Corbi (1989), half of the programmers’ task during software maintenance is involved in understanding the code. TDD approach will make the program becomes more comprehensive by encouraging the programmers to explain their code using test cases and code itself, rather than by using descriptive words. TDD will also ensure that the test cases are up to date.
  2. Efficiency: TDD researches believe that the fine granularity of the test-then-code cycle gives continuous feedback to the programmer. With TDD, faults are identified quickly as new code is added to the system; hence the source of the problem is more easily determined
  3. Test Assets: TDD enables testability. The use of the TDD practice drives programmers to write code that is automatically testable, such as having functions/methods returning a value that can be checked against expected results. The automated unit test cases written with TDD are valuable assets to the project.
  4. Reducing Defect Injection: D. Hamlet, J. Maybee (2001), assert that debugging and software maintenance are often perceived as a low-cost activity in which a working code defect is patched to alter its properties, and specifications and designs are neither examined nor updated.

Test Driven Development Best Practices:

According to Software Development Class’ guidance paper, these are the rules that one has to follow when using TDD method:

  1. Test First: Always make the test first before starting the development of the program. Remember the Red-Green-Refactor principle
  2. Acceptance Criteria: All the test refers to the Acceptance criteria written in the user story.
  3. Online Repository: All the development has to be posted in an online repository.
  4. Commit Milestone [RED]: The development has to be started with the test without the implementation.
  5. Clean test: Always remember the FIRST principles! (Fast, Isolated/Independent, Repeatable, Self-validating, Thorough/Timely).
  6. Commit Milestone [GREEN]: When the test has passed, push the code to the repository
  7. Code Coverage: Have to be 100%

Implementing Test Driven Development on Flutter:

I have been implementing Test-driven development on all of my task in this Software Development class. I would share a bit on how did I implement tests for the widget.

First, create the main.dart file if you have not set it up! At least it should be like this

import 'package:flutter/material.dart';void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}

Then, for example, you want to make a text form field. Try to make an empty class textForm.dart:

class textForm extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return null;
}
}

We do not have to implement the class right away. Instead, let’s make some test for determining what kind of output do we want to get? For example, we want to know if we have one text form field widget and a ‘Name’ text above it.

We could implement it in a file called textFormTest.dart. Do not forget to import your textForm.dart file!

import 'package:flutter/material.dart';

import 'package:flutter_test/flutter_test.dart';

void main() {
testWidgets('Render Test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());
expect(find.text('Name'), findsOneWidget);
expect(find.byType(TextFormField), findsOneWidget);
});
}

You can run the test now and get the result that your test has failed. Good!

Now let’s create the implementation for the class textForm.dart!

import 'package:flutter/material.dart';

class LoginPage extends StatefulWidget {

@override
State<StatefulWidget> createState() => new _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
@override
Widget build(BuildContext context) {
final name = TextFormField(
keyboardType: TextInputType.text,
style: TextStyle(color: Colors.white, fontSize: 16.0),
decoration: InputDecoration(
hintText: 'Name',
hintStyle: TextStyle(color: Colors.white),
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0),
borderSide: BorderSide(color: Colors.white),
),
prefixIcon: Icon(Icons.email, color: Colors.white,),
),
);

return Scaffold(
backgroundColor: Colors.lightBlueAccent,
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('lib/course.png'),
fit: BoxFit.cover,
)
),
child: Form(
child: ListView(
padding: EdgeInsets.only(top: 100.0, left: 50.0, right: 50.0),
children: <Widget>[
name,
SizedBox(height: 10.0),
],
),
)
),
);
}
}

Now finally, you can run the test file at the textFormTest.dart file and the test is supposed to return with a pass result now!

References:

  1. George, B., & Williams, L. (2004). A structured experiment of test-driven development. Information and Software Technology, 46(5), 337–342.
  2. Janzen, D., & Saiedian, H. (2005). Test-driven development concepts, taxonomy, and future direction. Computer, 38(9), 43–50.
  3. Kaufmann, R., & Janzen, D. S. (2003). Implications of Test-Driven Development: A Test Study. In Companion of the 18th annual ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications (p. 298).

--

--

Kezia Irene Tesiman
LEARNFAZZ

Biomedical Informatics Graduate Student at Harvard University. Interested in medical imaging, natural language processing, and machine learning.