Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TDD / Testability #19

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions content/_index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@ draft: false
* Module description can be found on canvas

This site contains the up-to-date course material, exercises and announcements about PRC2
(Programming Concepts 2: the Test Driven Way), starting in February 2024.
(Programming Concepts 2: the Test-Driven Way), starting in February 2025.

Responsible Teachers for 2024 PRC2:
Responsible Teachers for 2025 PRC2:

- Martijn Bonajo
- Ibrahim Kouzak
- Richard van den Ham

Most contents on this website were originally developed by Pieter van den Hombergh.
- Ibrahim Kouzak
- Lennart Tange

include::{topics}/literature.adoc[]

Expand Down
9 changes: 5 additions & 4 deletions content/docs/week01.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ test each and every part manually. You clicked on the nice TestMyCode (TMC) butt
There is a catch though: Out there in the real world, there won't be any button doing that magic for you, nor will some teacher or school
provide the tests for you, so [red]*you will be on your own*.#

But fret not! Writing tests is typically much simpler than writing the actual code. At least, it is when you follow a basic set of steps:
But fret not! Writing tests is typically much simpler than writing the actual code. At least it is, when you know the anatomy of a test:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AAA is more of an organisation-thingy.
In TDD, a helpful trick to learn can be to start with thinking of the 'Assert' part.
I'd therefore avoid thinking of them in steps.


. [blue]**A**rrange: Prepare or set up the thing you want to test
. [blue]**A**ct: Interact with the object you are testing
. [blue]**A**ssert or Ensure that the observable result(s) is/are as expected.
. If it says [red]*boom*, then at least you learned something ....
. [blue]**A**ssert that the observable result(s) is/are as expected

Finally, if a test says [red]*boom*, then at least you learned something ...

// :sectums!:
// == Reading
Expand All @@ -43,7 +44,7 @@ But fret not! Writing tests is typically much simpler than writing the actual co

* Test Driven Development.
* Maven configuration as exercise.
* **A**rrange **A**ct **A**ssert
* **A**rrange **A**ct **A**ssert.
* JUnit (5) as test framework.
* AssertJ as assertion library.

Expand Down
14 changes: 13 additions & 1 deletion content/docs/week02.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ date: 2022-02-01T14:17:33+01:00
draft: false
images: []
slug: "parameterized-tests"
menu:
menu:
docs:
parent: ""
weight: 020
Expand All @@ -14,6 +14,18 @@ toc: true

:imagesdir: /prc2_web/

== Clean tests
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think FIRST principles are helpful, not sure where they fit in best

  • week 1 seems pretty cramped already?
  • in week 2 it might give us a nice opportunity to revisit some fundamentals like TDD and AAA ?

Bad tests are anything but a pleasure to work with. They are slow, hard to understand, and hard to maintain.
In order to write clean tests, we follow the F.I.R.S.T. principles of tests:

// Source: Clean code, Robert C. Martin

- **Fast**: Tests should run quickly.
- **Independent**: Tests should not depend on each other. When the state of one test affects the outcome of another, it can be hard to understand why a test fails and makes it harder to run single tests or run tests in parallel.
- **Repeatable**: Tests should be repeatable in any environment. This means that tests should not depend on external resources like databases, network, or file systems.
- **Self-Validating**: Tests should be able to determine if they pass or fail without human intervention. This means that the test should contain assertions that determine if the test passes or fails.
- **Timely**: Tests should be written before the code they test. This is the essence of Test-Driven Development (TDD). If you write tests after the code, you might find out the code is hard to test.

include::{topics}/parameterizedtests.adoc[]

[TIP]
Expand Down
6 changes: 3 additions & 3 deletions content/docs/week03.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ date: 2022-02-02T11:28:06+01:00
draft: false
images: []
slug: "design-for-testability"
menu:
menu:
docs:
parent: ""
weight: 030
toc: true
---

include::{topics}/mockingandstubbing.adoc[]

include::{topics}/testability.adoc[]

include::{topics}/mockingandstubbing.adoc[]
Binary file added static/images/testability_tarlinder.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 22 additions & 8 deletions topics/testability.adoc
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
== Design for Test-ability

Also known as dependency injection made simple.
== Test-ability

[big]*A very important [green]#non functional# requirement of good software is [green]_Test-ability_. +
Test-ability can be achieved or improved by decoupling the class you are developing (the SUT) from it's environment, such that you have
full control over that environment in your test and can exactly control and observe what goes in or out of the SUT.*
A program that is not testable is not maintainable, because it takes a lot of effort to find out whether a change in the code has broken something else. *

What makes software testable?

image::testability_tarlinder.jpg[role="left", width=600, title="The testability attribute decomposed"]

- Controllability: How easy is it to bring the system in a state where you can test it?
- Observability: How easy is it to see what the system is doing?
- Smallness: How small is the system that you're testing?

Some examples where we have already seen test-ability in action. In PRC1, we already learned:
- In PRC1 we have seen that the UI is separated from the business logic. This allows us to test the business logic without the need of actually interacting with the UI. The same goes for the database, we can test the business logic without depending on the data in the database. (Controllability)
- We learned to never do nothing when we catch an exception. This allows us to test the exception handling in our code. (Observability)
- We learned to split up our code in small methods. This allows us to test the methods separately. But also to reuse the methods in other parts of the code to prevent having to test (and maintain) the same code in multiple places. (Smallness)



=== Writing test-able code

One first easy setup is to use [blue]*package private* visibility more often. It is actually the _default_ in java, and with reason.
When you then put your unit test in the same package (but it its own source tree), you can have the test class look at
or use the package private members of the class in its _assertion_ or verification very easily.
Most of unit testing is https://en.wikipedia.org/wiki/White-box_testing[white box testing] anyway, which almost always includes inspecting private members.
Keep in mind the test should be coupled to the *behavior* of the class, but as little as possible to its *implementation details*.

[NOTE]
====
For *business* code, organize your packages according to the collaborations the classes will have.
For *business* code, organize your packages according to the collaborations the classes will have.
In particular do [red]*NOT* organize classes according to type or kind,
like collections with collections and exceptions with exceptions. To express it as a metaphor: If you always keep your screws, seats, and back-rests in separate
rooms, they will never build chairs. You need to put them together, to make them cooperate. +
Expand All @@ -36,7 +50,7 @@ makes the application valuable, the rest is either plumbing or already available

[WARNING]
[red]*Never* let the business code _create_ its own persistence or or service object. You would
[big red]*loose control* over what flows between service and business class,
[red]*loose control* over what flows between service and business class,
and makes it [red]_unobservable_, which is bad from the testing standpoint.

Instead hand the service or resource to the business, or give it some provider of a resource.
Expand Down
8 changes: 4 additions & 4 deletions topics/topics.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
== Topics 2024 (preliminary)
== Topics 2025 (preliminary)

In the topics table below, *Vol I* is _Core Java Volume I, Fundamentals_ and *Vol II* is _Core Java Volume II, Advanced Features_
both by Cay S. Horstmann and both in the 12th edition.
Expand All @@ -16,8 +16,8 @@ both by Cay S. Horstmann and both in the 12th edition.
|link:docs/statemachine/[8] | State Machines | This website | Gumball Machine, Grade capture
|link:docs/reflection/[9] | Reflection | Vol I, ch. 5.9 | Table Generator, Genealogy
|link:docs/internationalisation/[10] | I18N / Exceptions / Logging | Vol I, ch. 7; Vol II, ch. 6 (time API) and 7 (LOgging) | Pub Exceptions
|11| Security | | tbd
|11| Security | | tbd
|12| Number systems and storage in Java | | tbd
|13| Concurrency | | tbd
|14| Buffer | |
|13| Concurrency | | tbd
|14| Buffer | |
|=======
Loading