Next time you have to learn a programming language, or a set of libraries from an ecosystem, put your learning under unit tests. It has 7 amazing advantages.
My story
Learning programming things by unit testing them is something I've done three times.
The first time and the original inspiration for this idea is the Kotlin Koans, a much believed way for Java developers to start learning Kotlin by running failing tests and fixing them one by one.
Kotlin / kotlin-koans-edu
Kotlin Koans for Educational Plugin and play.kotl.in
kotlin-koans-edu
Kotlin Koans are a series of exercises to get you familiar with the Kotlin Syntax. Each exercise is created as a failing unit test, and your job is to make it pass. You can work with Kotlin Koans in one of the following ways:
- You can play with Koans online: https://play.kotlinlang.org/koans/overview.
- You can solve the tasks right inside IntelliJ IDEA or Android Studio by installing the EduTools plugin and choosing Kotlin Koans course.
You don't need this project if you want to solve the tasks. Install the educational plugin or do it online. This project contains the task content, so please submit a new pull request if you want to contribute any changes to the existing or new tasks.
Later, I realized that while I had mastered the language, there was behind it a huge ecosystem of Java and Kotlin libraries, and I had no structured way of learning them. I was messing up inside my employer's main projects - and its 3 minutes compilation times - with my messed-up first attempts at understanding the library, and that does not count as a structured approach !
I remembered the experience of learning from the Kotlin Koans and wanted to have something similar. The kotlin-libraries-playgound
project came out of this simple idea, and grew and grew. Today it contains samples for [Apollo, CliKt, Kodein DI, Kodein DB, Exposed, Fuel, Hoplite, Klaxon, Konad, Konf, Kotlin Collections, Kotlin Faker, Kotlin IO, Kotlinpoet, Kotlin Statistics, Kotlinx Serialization, Ktor Client, Mordant, Moshi, OkHttp, OkIO, Picnic, Retrofit, Skrapeit, SqlDelight, Statemachine, ]https://github.com/LouisCAD/kotlin-libraries-playground/tree/main/kotlin-jvm/src/main/kotlin/playground), KoTest, Mockk, Spek, Strikt, Mockito, Junit-Jupiter, etc.
LouisCAD / kotlin-libraries-playground
A playground to gain a wider and deeper knowledge of the libraries in the Kotlin ecosystem. Also the official sample for gradle refreshVersions.
Kotlin Libraries Playground
A playground to gain a wider and deeper knowledge of the libraries in the Kotlin ecosystem
Also the official sample for gradle refreshVersions
Usage
Run all the samples
$ ./gradlew :kotlin-jvm:run
Run all the tests
$ ./gradlew :kotlin-testing:test
Test tests called FailingXXX are expected to fail
β€οΈ Contributors welcome! #hacktoberfest
We want to collect sample usage of Kotlin libraries, and the more the better!
You are very welcome to contribute your own library sample.
==> CONTRIBUTING.md
π€How do you keep up with all the new stuff?
There are great resources to learn Kotlin.
But once you master the language, you are not done just yet.
You now face another challenging task: become familiar with its ecosystem of libraries.
With time, you want to both acquire:
- a wider knowledge of what good libraries are available in the ecosystem in general
- a deeper knowledge of some specific librariesβ¦
But it was my third attempt that really cemented this practice in my mind.
This time, I needed to learn a new programming language and its huge ecosystem: Typescript and Node. Again I chose to learn by writing unit tests. You can find my project here:
Unit-testing my learning of Typescript and Node.js.
See https://dev.to/jmfayard/unit-test-your-knowledge-13j
What is in?
Mocha - the fun, simple, flexible JavaScript test framework
Libraries
- jsdom/jsdom: A JavaScript implementation of various web standards, for use with Node.js
- gcanti/fp-ts: Functional programming in TypeScript
- Introduction - fp-ts
- pluralize - This module uses a pre-defined list of rules, applied in order, to singularize or pluralize a given word. There are many cases where this is useful, such as any automation based on user input.
- showdown - Showdown is a Javascript Markdown to HTML converter
- lodash - A modern JavaScript utility library delivering modularity, performance & extras. Exposes many useful methods on JavaScript arrays, objects and other data structures.
Again I was delighted by the experience and I will try to explain why.
It starts with a simple mental switch.
Don't log, verify
When you follow the documentation of a programming language or library, you will typically read a piece of code that takes some input and transform it, before printing it to the console.
If you are like me, reading is not enough. The tutorial may explain things well, but only you can do the job of understanding it, and that usually requires getting your fingers dirty playing with the code.
Now the issue of just using console.log()
is that the results are gone as soon as you have logged them, you are on to the next thing. Whereas if you make a unit test out of it, you have a self-validating piece of code that you can execute over and over.
So don't stay here:
console.log(formatted)
// May 21st 2021, 3:20:04 pm
Do this instead:
it('format dates', function () {
const moment = moment('2021-05-21 15:20:04')
const formatted = moment.format('MMMM Do YYYY, h:mm:ss a')
expect(formatted).to.equal("May 21st 2021, 3:20:04 pm")
});
Get started with a pair-programming session
I started my node-playground repository by doing a pair-programming session with a friend.
I highly recommend this since it got many questions out of the way:
- Can you walk me through this package.json? What do I need to know?
- How do I add a library and its types?
- How do I add and configure typescript?
- I don't understand how imports work, can you explain?
- How do I setup a test runner? (mocha)
- Can you setup the tests in watch mode? (Yes)
- Which library do you recommend for the assertions? (chai)
- Can we write together a simple unit test for a library? (Moment.js)
Configuration gets in the way when you are getting started, so ask a human for help!
Get practical experience of writing the code in the IDE
Some learning websites have their own embedded text editors.
While this has its advantages (zero config), at the end of the day you must develop the skill of writing code in the IDE of your choice - Visual Studio Code, or Webstorm in my case -. Using this approach will get you plenty of practice.
Quick feedback
A big advantage of this approach is that you have a fast feedback loop.
The quick feedback loop inherent to this practice helps you get in the zone, as defined by Mihaly Csikszentmihalyi:
In positive psychology, a flow state, also known colloquially as being in the zone, is the mental state in which a person performing some activity is fully immersed in a feeling of energized focus, full involvement, and enjoyment in the process of the activity. In essence, flow is characterized by the complete absorption in what one does, and a resulting transformation in one's sense of time.
You advance steadily, test by step, stone by stone, in reversible steps.
Practice testing from day 1
A credibility issue that junior programmers have - and sadly even non-junior programmers - is that they have little experience with testing. "Getting" testing is an important hallmark on the way to professionalism.
But is testing hard?
I think the distinction from Rich Hickey: Simple is not Easy is important. Testing is a simple practice once you get it, but it's not easy in the sense that junior programmers don't have lots of experience with it, if at all.
But if you practice testing from day 1, it sure won't feel that hard the day you are hired!
A mentor can easily review your work
Another advantage of having your learning contained in a GitHub repository is that it makes it easy for a mentor to review your work. Add them as collaborators to your project and ask them what they would change in your codebase. Then look at the diff together, it's a great way to start a conversation about what you need to learn next.
Keep your knowledge up-to-date
This one especially applies to unit tests for libraries like in the kotlin-libraries-playground project. Since the code is self-validating, you can update the dependencies and see what has changed and what was broken. Yes, it's work, but it's useful work. It keeps your validated knowledge fresh.
Use the repository for bug reports
The Kotlin libraries playground has also been very effective for me to report bugs. When I was facing an issue with an external dependency, I created a new branch and added the minimum amount of code that reproduced the problem. Having reproducing steps helps the maintainer to provide you a fix more quickly.
Proof of knowledge for job interviews
This one is big. You know the traditional dilemma: you want to have your first programming job with $LANGUAGE, but you are getting rejected because you don't have experience in it yet.
The way out of this non-sense is to show that you have acquired enough knowledge with it. Sure enough, having a public repository that demonstrates your knowledge is a great way to do that.
Conclusion
Writing unit tests on what you are currently learning provides for a great developer experience, similar to what professional developers do. With time it becomes a public repository of your validated knowledge, which can stay up-to-date, and is useful for getting feedback, reporting bugs or demonstrating your skills in the context of a job interview.
It goes hand in hand with the good tip of writing and publishing real projects. Putting out a new project is like assembling a new puzzle. Writing unit tests is all about understanding better what each piece of the puzzle does.
If you want to contact me, read my standing invitation at https://jmfayard.dev/contact/
Top comments (2)
Great article
Glad you like it :)