工程師與貓
Published in

工程師與貓

Testing — TDD and Unit Testing

近況更新

入職到現在也已經要半年了,工作內容主要是用react native做APP,所以之前的Android side project就暫停了。這篇文章也是因為前陣子公司開始準備寫測試,所以便紀錄了一下學習心得的重點。關於測試的文章大概會分三篇,第一篇便是這篇,闡述了一下TDD跟Unit test。第二篇會著重在藉由DI(dependency injection)的例子介紹mock。最後一篇則會介紹到寫測試時要考慮到哪些test cases與boundary case,因為畢竟測試是沒有寫完的一天...

TDD

What is TDD?

  • From wiki:
  • Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: requirements are turned into very specific test cases, then the software is improved to pass the new tests, only.
  • 測試驅動開發 是一種軟體開發過程中的應用方法,是一種非常短的重複性開發流程,將需求轉變為非常具體的測試案例,然後改善軟體,使其僅通過新的測試案例。

Why TDD?

  • KISS 原則是指在設計當中應當注重簡約的原則,YAGNI則指不應該為程式碼加入尚未用到的功能。
  • “keep it simple, stupid” (KISS) and “You aren’t gonna need it” (YAGNI). By focusing on writing only the code necessary to pass tests, designs can often be cleaner and clearer than is achieved by other methods
  • 可測性
  • Testability
  • 更深入和更早地了解產品要求
  • deeper and earlier understanding of the product requirements

The comparaison of costs:

The time spent:

How to do TDD?

  1. 加入一個測試 Add a test
  • 必須了解整個功能的規格跟要求
  • must clearly understand the feature’s specification and requirements
  • 軟體開發者可透過使用者案例跟使用者故事去涵蓋這些產品要求跟例外情況
  • The developer can accomplish this through use cases and user stories to cover the requirements and exception conditions
  • 讓開發者可在開發前,專注在產品要求上
  • makes the developer focus on the requirements before writing the code

2. 跑所有測試,並確保這個新加入的測試結果為失敗的 Run all tests and see if the new test fails

3. 開發程式 Write the code

4. 跑測試 Run tests

5. 重構程式 Refactor code

  • 移除重複的程式碼
  • Duplication must be removed
  • 物件,類別,模組,變數以及方法名稱應清楚表達他們的目的與使用
  • Object, class, module, variable and method names should clearly represent their current purpose and use
  • 在每一次的重構階段,藉由重複性的跑這些測試案例可以讓程式開發者建立信心,確保每一次的重構並沒有改變現存的所有功能
  • By continually re-running the test cases throughout each refactoring phase, the developer can be confident that process is not altering any existing functionality

Repeat

  • “red/green/refactor”

Keep the unit small

  • For TDD, a unit is most commonly defined as a class, or a group of related functions often called a module. Benefits including:
  • Reduced debugging effort — When test failures are detected, having smaller units aids in tracking down errors
  • Self-documenting tests — Small test cases are easier to read and to understand
  • Better practice:
  • acceptance test–driven development (ATDD) and
  • unit test-driven development(UTDD)

Unit Test

What is unit test?

  • 一個單元為程式中最小可測試單位
  • a unit as the smallest testable part of an application
  • 理想情況下,每個測試用例都獨立於其他測試用例,單元測試通常不應超出其自身的單位邊界
  • Ideally, each test case is independent from the others, a unit test should usually not go outside of its own unit boundary

Why unit test?

  • 建造解耦且有凝聚力的程式碼
  • create decoupled and cohesive code bodies
  • 藉由從程式中抽取出這些必要的附件(暫時減少耦合),獨立單元可以比以前進行更徹底的測試。 可使得我們有更高質量的單元,也更易於維護
  • By abstracting this necessary attachment from the code (temporarily reducing the net effective coupling), the independent unit can be more thoroughly tested than may have been previously achieved. This results in a higher-quality unit that is also more maintainable
  • 隔離程式的每個部分,並確保各個部分是正確的
  • isolate each part of the program and show that the individual parts are correct
  • 讓軟體工程師可以進行重構
  • allows the programmer to refactor code or upgrade system libraries

Good Principles:

F.I.R.S.T

  • 快速 Fast
  • One of the major cause of slow tests — is dependency that must handle external evil necessities such as databases, files, and network calls. They take thousands of milliseconds. So to make suite fast, you must avoid creating these dependencies by using mock testing.
  • 隔離 Isolated
  • Never ever write tests which depend on other test cases. No order-of-run dependency.
  • Do not do any more actions after the assert statement(s), preferably single logical assert.
  • 重複 Repeatable
  • set up a private sandbox to avoid conflicts with other developers whose tests concurrently alter the database, use in-memory databases.
  • Each test should setup or arrange it’s own data. create a helper function if have common data structures with other test cases
  • 自我驗證 Self-validating
  • Each test must be able to determine that the output is expected or not
  • 適時/徹底 Timely/Thorough
  • Should cover every use case scenario and NOT just aim for 100% coverage.
  • Tests for corner/edge/boundary values.
  • Tests for large data sets
  • Tests for large values — overflow and underflow errors for data types like integer.
  • Tests for exceptions and errors.
  • Tests for illegal arguments or bad inputs.

3A

  • arrange
  • act
  • assert

Other Good principles

  • Know what you’re testing
  • use the scenario tested and expected result as part of the test method name. When a developer has a problem naming a test, that means the test lacks focus.
  • Naming conventions
  • When a well-named test fails, it is easier to understand what was tested and why it failed.
  • Do repeat yourself
  • Readability is very important in unit testing, so it is acceptable to have duplicate code.
  • Test results, not implementation
  • Successful unit testing requires writing tests that would only fail in case of an actual error or requirement change.
  • Avoid overspecification
  • Use an Isolation framework

Additional

What is the difference between TDD and unit test?

The purpose of a unit test is to give a developer confidence that a particular part of their application behaves in the way that the developer expects. This is very valuable for regression testing. If you modify code that is covered by unit tests, then you can use the tests to immediately determine whether you have broken existing functionality.

So how does a TDD test differ from a unit test? Unlike a unit test, a TDD test is used to drive the design of an application. A TDD test is used to express what application code should do before the application code is actually written.

Like unit tests, TDD tests can be used for regression testing. You can use TDD tests to immediately determine whether a change in code has broken existing application functionality. However, unlike a unit test, a TDD test does not necessarily test one unit of code in isolation.

Like acceptance tests, TDD tests are used to drive the creation of an application. TDD tests work like mini-acceptance tests. You create a TDD test to express the application functionality that needs to be implemented next. However, unlike an acceptance test, a TDD test is not an end-to-end test. A TDD test does not interact with a live database or web server.

What is regression test?

  • Regression testing is re-running functional and non-functional tests to ensure that previously developed and tested software still performs after a change. If not, that would be called a regression. Changes that may require regression testing include bug fixes, software enhancements, configuration changes, and even substitution of electronic components.

Reference:

https://en.wikipedia.org/wiki/Test-driven_development

https://en.wikipedia.org/wiki/Unit_testing

http://agiledata.org/essays/tdd.html

http://stephenwalther.com/archive/2009/04/11/tdd-tests-are-not-unit-tests

https://hackernoon.com/test-f-i-r-s-t-65e42f3adc17

https://esj.com/Articles/2012/09/24/Better-Unit-Testing.aspx?Page=1

https://www.ca.com/en/blog-agile-requirements-designer/guide-to-test-driven-development-tdd-vs-bdd-vs-atdd.html

https://howtodoinjava.com/best-practices/first-principles-for-good-tests/

https://github.com/ghsukumar/SFDC_Best_Practices/wiki/F.I.R.S.T-Principles-of-Unit-Testing

https://builttoadapt.io/why-tdd-489fdcdda05e

https://medium.freecodecamp.org/test-driven-development-what-it-is-and-what-it-is-not-41fa6bca02a2

https://medium.com/javascript-scene/the-outrageous-cost-of-skipping-tdd-code-reviews-57887064c412

--

--

--

一點程式 / 一點心得 / 一點貓 / 一點美食

Recommended from Medium

[2022] Crack DP-203 Microsoft Certified Azure Data Engineer Associate

44 New Cool Websites and Apps to Learn Something New

Time Tracking in the Agile Process

A Brief Overview of Agile Methodology in 2022

Top 10 Flutter Database, that you should know about it

How to use tfsec in the pipeline

How to Test a JavaScript Application Like a Pro? (Part 1)

How to Deploy Grafana & Prometheus in Kubernetes Cluster.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alex Yu

Alex Yu

Hello, I'm a developer who learned ReactJS at beginning, and then my cat named Mocha. That's right, he is always going to test my codes.

More from Medium

Static Subroutines and Static Variables

Design Patterns — Prototype Pattern

Code quality via static typing — Part 1

Solid Principles