• Search in book...
• Toggle Font Controls

# Chapter 2. Multi-currency Money

Followed fast and followed faster

Edgar Allen Poe, The Raven

Did the RED-GREEN-REFACTOR cycle we followed in Chapter 1 seem a tad too slow?

A response of “heck yes!” (or some rhyming phrase) is understandable!

The goal of test-driven development isn’t to force us to go slow. Or fast, for that matter. Its goal is to allow us to go at a pace we’re comfortable with: speeding up when we can, slowing down when we should.

In this chapter, we’ll introduce additional currencies and the ability to multiply and divide money in any currency. Let’s see if we can kick up the pace a bit.

# Enter the Euro

The second item on our list of features introduces a new currency:

 5 USD x 2 = 10 USD 10 EUR x 2 = 20 EUR 4002 KRW / 4 = 1000.5 KRW 5 USD + 10 EUR = 17 USD 1 USD + 1100 KRW = 2200 KRW

This indicates that we need a more general entity than the `Dollar` we created in the previous chapter. Something like `Money`, which encapsulates an `amount` (which we already have) and a `currency` (which we do not yet have). Let’s write tests to flush out this new feature.

## Go

Let’s write a new test in `money_test.go`. This test requires that when a struct representing “10 Euros” is multiplied by 2, we get “20 Euros”:

````func` `TestMultiplicationInEuros``(``t` `*``testing``.``T``)` `{`
`tenEuros` `:=` `Money``{``amount``:` `10``,` `currency``:` `"EUR"``}`
`twentyEuros` `:=` `tenEuros``.``Times``(``2``)`
`if` `twentyEuros``.``amount` `!=` `20` `{`
`t``.``Errorf``(``"Expected 20, got: [%d]"``,` `twentyEuros``.``amount``)`
`}`
`if` `twentyEuros``.``currency` `!=` `"EUR"` `{`
`t``.``Errorf``(``"Expected EUR, got: [%s]"``,` `twentyEuros``.``currency``)`
`}`
`}````

The test expresses the concepts of “10 Euros” and “20 Euros” with `struct` instances containing a `currency` as well as `amount`.

By now, we know that when we run this test, we’ll get an error notifying us of `undefined: Money`. We can eliminate this by introducing a new struct:

````type` `Money` `struct` `{`
`amount`   `int`
`currency` `string`
`}````

We now get the error `type Money has no field or method Times`, which we know how to get around. We define a `Times` method for `Money`:

````func` `(``m` `Money``)` `Times``(``multiplier` `int``)` `Money` `{`
`return` `Money``{``amount``:` `m``.``amount` `*` `multiplier``,` `currency``:` `m``.``currency``}`
`}````

Yay! Green tests again.

## JavaScript

Let’s write a test for representing a `Money` object with `amount` and `currency`. We verify that when an object representing “10 Euros” is multiplied by 2, we get “20 Euros”. We define this test at the very end of `test_money.js`:

````tenEuros` `=` `new` `Money``(``10``,` `"EUR"``);`
`twentyEuros` `=` `tenEuros``.``times``(``2``);`
`assert``.``strictEqual``(``twentyEuros``.``amount``,` `20``);`
`assert``.``strictEqual``(``twentyEuros``.``currency``,` `"EUR"``);````

By now, we anticipate the `ReferenceError: Money is not defined` error we get when running the tests. We can eliminate this by introducing a new class named `Money` with the minimally desired behavior, that is: a `constructor` that initializes both `amount` and `currency`, and a `times` method that multiplies the `amount` with a given `multiplier` and returns a new `Money` object.

````class` `Money` `{`
`constructor``(``amount``,` `currency``)` `{`
`this``.``amount` `=` `amount``;`
`this``.``currency` `=` `currency``;`
`}`

`times``(``multiplier``)` `{`
`return` `new` `Money``(``this``.``amount` `*` `multiplier``,` `this``.``currency``);`
`}`
`}````

Yay! Both our tests are now green.

## Python

Let’s add a new test in the `TestMoney` class. This test would verify that multiplying an object representing “10 Euros” by 2 gives us an object representing “20 Euros”:

```  `def` `testMultiplicationInEuros``(``self``):`
`tenEuros` `=` `Money``(``10``,` `"EUR"``)`
`twentyEuros` `=` `tenEuros``.``times``(``2``)`
`self``.``assertEqual``(``20``,` `twentyEuros``.``amount``)`
`self``.``assertEqual``(``"EUR"``,` `twentyEuros``.``currency``)````

By now, we anticipate the `NameError: name 'Money' is not defined` error we get when we run the tests. We can get rid of this error by introducing a new `Money` class with the minimally necessary behavior. This means an `__init__` method that initializes both `amount` and `currency`, and a `times` method that returns a new `Money` object whose `amount` is a product of the `multiplier` and the `amount` of the original `Money` object:

````class` `Money``:`
`def` `__init__``(``self``,` `amount``,` `currency``):`
`self``.``amount` `=` `amount`
`self``.``currency` `=` `currency`

`def` `times``(``self``,` `multiplier``):`
`return` `Money``(``self``.``amount` `*` `multiplier``,` `self``.``currency``)````

Yay! Both our tests are now green.

# Keeping code DRY

Wait a minute: didn’t we just create a horrendous duplication in our code? The new entity we created to represent `Money` subsumes what we wrote earlier for `Dollar`. This can’t possibly be good. A oft-quoted rule in writing code is the DRY principle: Don’t Repeat Yourself.

Recall the RED-GREEN-REFACTOR cycle. What we did in the previous section got us to green, but we haven’t done the necessary refactoring yet. Let’s remove the duplication in the code while keeping our tests green.

## Go

We realize that the `Money` struct can do everything that the `Dollar` struct can, and more. `Money` has `currency`, which `Dollar` does not.

Let’s delete the `Dollar` struct and its `Times` method.

When we do this, the `TestMultiplication` test predictably breaks with an `undefined: Dollar` error. Let’s refactor that test to use `Money` instead:

````func` `TestMultiplicationInDollars``(``t` `*``testing``.``T``)` `{`
`fiver` `:=` `Money``{``amount``:` `5``,` `currency``:` `"USD"``}`
`tenner` `:=` `fiver``.``Times``(``2``)`
`if` `tenner``.``amount` `!=` `10` `{`
`t``.``Errorf``(``"Expected 10, got: [%d]"``,` `tenner``.``amount``)`
`}`
`if` `tenner``.``currency` `!=` `"USD"` `{`
`t``.``Errorf``(``"Expected USD, got: [%s]"``,` `tenner``.``currency``)`
`}`
`}````

Both tests now pass. Notice that we renamed the test to be more descriptive: `TestMultiplicationInDollars`.

## JavaScript

The `Money` class can do everything that `Dollar` does, and more. This means that we can delete the `Dollar` class in its entirety.

When we do this and run the tests, we get our old friendly error: `ReferenceError: Dollar is not defined`. Let’s refactor the first test to use `Money` instead:

````fiver` `=` `new` `Money``(``5``,` `"USD"``);`
`tenner` `=` `fiver``.``times``(``2``);`
`assert``.``strictEqual``(``tenner``.``amount``,` `10``);`
`assert``.``strictEqual``(``tenner``.``currency``,` `"USD"``);````

Both tests now pass.

## Python

The `Money` class’s functionality is a superset of that of the `Dollar` class. Which means we don’t need the latter. Let’s delete the `Dollar` class in its entirety.

Having done this, we get the familiar `NameError: name 'Dollar' is not defined` message when we run the tests. Let’s refactor the first test to use `Money` instead of the erstwhile `Dollar`:

```  `def` `testMultiplicationInDollars``(``self``):`
`fiver` `=` `Money``(``5``,` `"USD"``)`
`tenner` `=` `fiver``.``times``(``2``)`
`self``.``assertEqual``(``10``,` `tenner``.``amount``)`
`self``.``assertEqual``(``"USD"``,` `tenner``.``currency``)````

Both tests now pass. Notice that we renamed the test to be more descriptive: `testMultiplicationInDollars`.

# Didn’t we just say “Don’t Repeat Yourself”?!

Hmm. The two tests — the one for Dollars and the one for Euros — are very similar. The currencies and amounts vary, but they test pretty much the same feature.

Repetition in code comes in varied forms. Sometimes we have identical lines of code (perhaps caused by “copy pasta” programming). In these cases, extracting the common lines to a function or method is what we need to do. At other times, we have parts of code that are not identical, but conceptually similar. This is the case with our two tests.

We could delete one of the tests and still feel confident about our code. However, we also want to safeguard ourselves against accidental regression in our code. Recall that our very first implementation used hard-coded numbers (`10` or `5 * 2`). Having two distinct tests with different values ensures that we won’t accidentally go back to that naive implementation.

###### Tip

Regression — “a return to a primitive or less developed state" — is a common theme in writing software. Having a battery of tests is a reliable way to ensure that we don’t break existing features as we build new ones.

Let’s keep both test cases for now. We’ll add an item to the end of our checklist noting our desire to remove redundancy in tests. We’ll revisit this item later, after we address division.

Here’s our feature list:

 5 USD x 2 = 10 USD 10 EUR x 2 = 20 EUR 4002 KRW / 4 = 1000.5 KRW 5 USD + 10 EUR = 17 USD 1 USD + 1100 KRW = 2200 KRW Remove redundant `Money` multiplication tests

# Divide and Conquer

The next requirement is to allow division. On the surface, it looks very similar to multiplication. We know from elementary mathematics that dividing by x is the same as multiplying by 1⁠/⁠x. 1

Let’s test-drive this new feature and see how our code evolves. By now, we are getting into the groove of starting with a failing test. As an indicator of our growing confidence, we’ll introduce two new things in our test:

1. A new currency: Korean Won (KRW), and

2. Numbers with fractional parts, e.g. 1000.5

## Go

Let’s write our new test for division.

````func` `TestDivision``(``t` `*``testing``.``T``)` `{`
`originalMoney` `:=` `Money``{``amount``:` `4002``,` `currency``:` `"KRW"``}`
`actualMoneyAfterDivision` `:=` `originalMoney``.``Divide``(``4``)`
`expectedMoneyAfterDivision` `:=` `Money``{``amount``:` `1000.5``,` `currency``:` `"KRW"``}`
`if` `expectedMoneyAfterDivision` `!=` `actualMoneyAfterDivision` `{`
`t``.``Errorf``(``"Expected  [%+v] Got: [%+v]"``,`
`expectedMoneyAfterDivision``,` `actualMoneyAfterDivision``)`
`}`
`}````

Notice that we wrote this test a bit differently. We define variables for the two structs: `actualMoneyAfterDivision` and `expectedMoneyAfterDivision`. And instead of comparing `amount` and `currency` separately, we compare the two structs as a whole. If the structs don’t match, we print them both.

###### Tip

In Go, printing a struct with the `%+v` format “verb” prints the struct’s field names as well as values.

We anticipate the `type Money has no field or method Divide` error we get when we run this test. Let’s define this missing method, taking our cue from the existing `Times` method:

````func` `(``m` `Money``)` `Divide``(``divisor` `int``)` `Money` `{`
`return` `Money``{``amount``:` `m``.``amount` `/` `divisor``,` `currency``:` `m``.``currency``}`
`}````

Ah! The test fails with a new error: `constant 1000.5 truncated to integer`.

It’s clear that we need to change the `amount` field in the `Money` struct so that it can hold fractional values. The `float64` data type is appropriate for this purpose:

````type` `Money` `struct` `{`
`amount`   `float64`
`currency` `string`
`}````

This gives us new errors when we run our test:

````...` `invalid` `operation``:` `m``.``amount` `*` `multiplier` `(``mismatched` `types` `float64` `and` `int``)`
`...` `invalid` `operation``:` `m``.``amount` `/` `divisor` `(``mismatched` `types` `float64` `and` `int``)````
###### Tip

Using an IDE can be useful because it flags syntax errors and type errors without any need to run the tests.

We need to modify our arithmetic operations (multiplication and division) to use the same data type for all operands. We know from our domain that the multipliers and divisors are likely to be integers (number of shares of a stock) whereas the amount can be a fractional number (trading price of a particular stock). Let’s use this knowledge to convert the `multiplier` and `divisor` to `float64` before using them in our arithmetic operations. We can do this by calling the `float64()` function:

````func` `(``m` `Money``)` `Times``(``multiplier` `int``)` `Money` `{`
`return` `Money``{``amount``:` `m``.``amount` `*` `float64``(``multiplier``),` `currency``:` `m``.``currency``}`
`}`

`func` `(``m` `Money``)` `Divide``(``divisor` `int``)` `Money` `{`
`return` `Money``{``amount``:` `m``.``amount` `/` `float64``(``divisor``),` `currency``:` `m``.``currency``}`
`}````

Now we get different `wrong type` failures

````...` `Errorf` `format` `%``d` `has` `arg` `tenner``.``amount` `of` `wrong` `type` `float64`
`...` `Errorf` `format` `%``d` `has` `arg` `twentyEuros``.``amount` `of` `wrong` `type` `float64````

A careful reading of the error messages reveals that we are using the wrong format “verb” in our earlier tests to print the `amount` field. Since our newest test — `TestDivision` — successfully compares entire `struct`s, we can refactor our earlier two multiplication tests to do something similar. This way, we'll side-step the whole issue of having used the incorrect formatting "verb" for `float64` type.

Here’s how `TestMultiplicationInDollars` looks after changing its assertion statement. (The other test, `TestMultiplicationInEuros`, needs similar changes.)

````func` `TestMultiplicationInDollars``(``t` `*``testing``.``T``)` `{`
`fiver` `:=` `Money``{``amount``:` `5``,` `currency``:` `"USD"``}`
`actualResult` `:=` `fiver``.``Times``(``2``)`
`expectedResult` `:=` `Money``{``amount``:` `10``,` `currency``:` `"USD"``}`
`if` `actualResult` `!=` `actualResult` `{`
`t``.``Errorf``(``"Expected [%+v], got: [%+v]"``,` `expectedResult``,` `actualResult``)`
`}`
`}````
###### Tip

If compilation or assertion failures crop up during a test run, pay attention to the error messages.

After these changes, all our tests are green.

## JavaScript

Let’s write our new test for division at the end of `test_money.js`.

````originalMoney` `=` `new` `Money``(``4002``,` `"KRW"``)`
`actualMoneyAfterDivision` `=` `originalMoney``.``divide``(``4``)`
`expectedMoneyAfterDivision` `=` `new` `Money``(``1000.5``,` `"KRW"``)`
`assert``.``deepStrictEqual``(``actualMoneyAfterDivision``,` `expectedMoneyAfterDivision``)````

Notice that we wrote this test a bit differently. We define variables for the two objects: `actualMoneyAfterDivision` and `expectedMoneyAfterDivision`. And instead of comparing `amount` and `currency` separately, we compare the two objects at once using the `deepStrictEqual` method in `assert`.

###### Tip

In Node.js’s `assert` module, the `deepStrictEqual` method compares two objects and their child objects for equality using the JavaScript === operator. 2

We anticipate the `TypeError: originalMoney.divide is not a function` error we get when we run this test. So let’s define this missing method, taking inspiration from the existing `times` method. 3

````class` `Money` `{`

`...`

`divide``(``divisor``)` `{`
`return` `new` `Money``(``this``.``amount` `/` `divisor``,` `this``.``currency``);`
`}`
`}````

Yay! The tests are all green. JavaScript’s dynamic types make implementing this feature easier than languages with static typing.

## Python

Let’s write our new test for division in class `TestMoney`:

```  `def` `testDivision``(``self``):`
`originalMoney` `=` `Money``(``4002``,` `"KRW"``)`
`actualMoneyAfterDivision` `=` `originalMoney``.``divide``(``4``)`
`expectedMoneyAfterDivision` `=` `Money``(``1000.5``,` `"KRW"``)`
`self``.``assertEqual``(``expectedMoneyAfterDivision``.``amount``,`
`actualMoneyAfterDivision``.``amount``)`
`self``.``assertEqual``(``expectedMoneyAfterDivision``.``currency``,`
`actualMoneyAfterDivision``.``currency``)````

Notice that we wrote this test a bit differently. We define variables for the two objects: `actualMoneyAfterDivision` and `expectedMoneyAfterDivision`.

We anticipate the `AttributeError: 'Money' object has no attribute 'divide'` message we get when we run this test. So let’s define this missing method, taking our cue from the existing `times` method: 4

```  `def` `divide``(``self``,` `divisor``):`
`return` `Money``(``self``.``amount` `/` `divisor``,` `self``.``currency``)````

Yay! The tests are green. Python is a dynamically (and strongly) typed language. This makes implementing this feature easier than languages with static typing.

# Cleaning Up

Let’s finish off this chapter with a bit of house cleaning, while keeping the tests green.

## Go

We now have three tests with three assertion blocks, each of which is a 3-line `if` block. Except for the variable names in each test, the `if` blocks are identical. This duplication is ripe for removal via extracted into a helper function, which we can call `assertEqual`.

###### Tip

“Extract method” or “Extract function” is a common refactoring. It involves replacing common blocks of code with a call to a new function/method that encapsulates the block of code once.

````func` `assertEqual``(``t` `*``testing``.``T``,` `expected` `Money``,` `actual` `Money``)` `{`
`if` `expected` `!=` `actual` `{`
`t``.``Errorf``(``"Expected  [%+v] Got: [%+v]"``,` `expected``,` `actual``)`
`}`
`}````

The function’s body is identical to any of the three existing `if` blocks. We can now call this function from each of the three tests. The `TestDivision` function is shown below:

````func` `TestDivision``(``t` `*``testing``.``T``)` `{`
`originalMoney` `:=` `Money``{``amount``:` `4002``,` `currency``:` `"KRW"``}`
`actualResult` `:=` `originalMoney``.``Divide``(``4``)`
`expectedResult` `:=` `Money``{``amount``:` `1000.5``,` `currency``:` `"KRW"``}`
`assertEqual``(``t``,` `expectedResult``,` `actualResult``)`
`}````

We can modify the `TestMultiplicationInEuros` and `TestMultiplicationInDollars` tests similarly.

## JavaScript

The assertion using `deepStrictEqual` that we used for our last test is elegant: it compares the two objects (expected value and actual value) at once. We can use it for our two other tests.

While we’re doing it, we can also address a subtle assumption in these two lines of code in our tests:

````tenner` `=` `fiver``.``times``(``2``);`
`...`
`twentyEuros` `=` `tenEuros``.``times``(``2``);````

From the perspective of the test, it is a bit presumptuous to assume that multiplying 5 Dollars or 10 Euros by two will yield 10 Dollars or 20 Euros, respectively. Indeed, that’s the very thing the tests purport to verify. We can improve our tests by inlining the call to the `times` method, thereby saving ourselves the trouble of naming the variable:

````fiveDollars` `=` `new` `Money``(``5``,` `"USD"``);`
`tenDollars` `=` `new` `Money``(``10``,` `"USD"``);`
`assert``.``deepStrictEqual``(``fiveDollars``.``times``(``2``),` `tenDollars``);````
###### Tip

“Inline variable” is a refactoring that replaces a named variable with an directly evaluated (usually anonymous) variable.

We can refactor the test for multiplying Euros similarly.

## Python

Comparing two `Money` objects piecemeal is verbose and tedious. In our tests, we verify that the `amount` and `currency` fields of `Money` objects are equal, over and over. Wouldn’t it be nice to be able to compare two `Money` objects directly in a single line of code?

In Python, object equality is ultimately resolved by an invocation of the `__eq__` method. By default, this method returns true if the two object references being compared in fact point to the same object. This is a very strict definition of equality: it means that an object is only equal to itself, not any other object, even of the two objects have the same state.

###### Important

The default implementation of `__eq__` method means that in Python, two object references are equal if and only if they point to the same object. That is: https://docs.python.org/3/reference/datamodel.html#object.eq[equality is determined by reference, not by value].

Fortunately, it is not only possible but recommended to override the `__eq__` method when needed. Let us explicitly override this method within the definition of our `Money` class:

````class` `Money``:`

`...`

`def` `__eq__``(``self``,` `other``):`
`return` `self``.``amount` `==` `other``.``amount` `and` `self``.``currency` `==` `other``.``currency````

After defining the `__eq__` method, we can compare `Money` objects in a single line.

While we’re refactoring, we can also address a subtle assumption implicit in how we named a couple of variables in our tests:

````tenner` `=` `fiver``.``times``(``2``)`
`...`
`twentyEuros` `=` `tenEuros``.``times``(``2``)````

From the test’s perspective, it isn’t a given that multiplying 5 Dollars or 10 Euros by two will yield 10 Dollars or 20 Euros, respectively. Indeed, that’s the very thing the test exists to validate. We can improve our tests by doing an inline-variable refactoring, along with the single-line assertion that we can now write.

Here’s the complete `testMultiplicationInDollars` :

```  `def` `testMultiplicationInDollars``(``self``):`
`fiveDollars` `=` `Money``(``5``,` `"USD"``)`
`tenDollars` `=` `Money``(``10``,` `"USD"``)`
`self``.``assertEqual``(``tenDollars``,` `fiveDollars``.``times``(``2``))````

We initialize `fiveDollars` and `tenDollars` explicitly. We then verify that multiplying the former by 2 yields an object that’s equal to the latter. We also do it in one line, keeping our code readable and succinct.

The other two tests can be refactored similarly.

# Committing Our Changes

We have written a couple more tests and the associated code to make them green. Time to commit these changes to our local Git repository.

````git`` ``add`` ``.`` ````
````git`` ``commit`` ``-m`` ``"feat: division and multiplication features done"`` ````

Add all files, including all changes in them, to the Git index

Commit the Git index to the repository with the given message

At this point, we have two commits in our Git history, a fact we can verify by examining the output of `git log`:

````commit`` ``1e43b6e6731407a810601d973c83b406249f4d59`` ``(``HEAD`` ``->`` ``main``)`` ````
````Author:`` ``Saleem`` ``Siddiqui`` ``...````
````Date:``   ``Sun`` ``Mar`` ``7`` ``12:58:47`` ``2021`` ``-0600````

````feat:`` ``division`` ``and`` ``multiplication`` ``features`` ``done`` ````

````commit`` ``bb31b94e90029ddeeee89f3ca0fe099ea7556603`` ````
````Author:`` ``Saleem`` ``Siddiqui`` ``...````
````Date:``   ``Sun`` ``Mar`` ``7`` ``12:26:06`` ``2021`` ``-0600````

````chore:`` ``first`` ``green`` ``test````

New SHA hash for our second commit, which represents the HEAD of the Git repository

The message we used for our second commit

[.small]#The SHA hash for our previous commit from Chapter 1 #

# Where We Are

In this chapter, we built a second feature, division, and modified our design to deal with numbers with fractions. We have introduced a `Money` entity that allows us to consolidate how Dollars and Euros (and potentially other currencies) are multiplied by a number. We have a couple of passing tests. We have also cleaned up our code along the way.

###### Important

Depending on the specific data types and language, floating point arithmetic can cause problems of overflow/underflow. If needed, the problems can be surfaced via tests, and then solved — using RGR cycle. We also refactored our code to make it succinct and expressive.

With a couple more features crossed off our list, we’re ready to look at adding up amounts in different currencies — which will get our attention in the next chapter.

Here’s where we are in our feature list:

 5 USD x 2 = 10 USD 10 EUR x 2 = 20 EUR 4002 KRW / 4 = 1000.5 KRW 5 USD + 10 EUR = 17 USD 1 USD + 1100 KRW = 2200 KRW Remove redundant `Money` multiplication tests

## Go

Here’s how the file `money_test.go` looks right now:

````package` `main`

`import` `(`
`"testing"`
`)`

`func` `TestMultiplicationInDollars``(``t` `*``testing``.``T``)` `{`
`fiver` `:=` `Money``{``amount``:` `5``,` `currency``:` `"USD"``}`
`actualResult` `:=` `fiver``.``Times``(``2``)`
`expectedResult` `:=` `Money``{``amount``:` `10``,` `currency``:` `"USD"``}`
`assertEqual``(``t``,` `expectedResult``,` `actualResult``)`
`}`

`func` `TestMultiplicationInEuros``(``t` `*``testing``.``T``)` `{`
`tenEuros` `:=` `Money``{``amount``:` `10``,` `currency``:` `"EUR"``}`
`actualResult` `:=` `tenEuros``.``Times``(``2``)`
`expectedResult` `:=` `Money``{``amount``:` `20``,` `currency``:` `"EUR"``}`
`assertEqual``(``t``,` `expectedResult``,` `actualResult``)`
`}`

`func` `TestDivision``(``t` `*``testing``.``T``)` `{`
`originalMoney` `:=` `Money``{``amount``:` `4002``,` `currency``:` `"KRW"``}`
`actualResult` `:=` `originalMoney``.``Divide``(``4``)`
`expectedResult` `:=` `Money``{``amount``:` `1000.5``,` `currency``:` `"KRW"``}`
`assertEqual``(``t``,` `expectedResult``,` `actualResult``)`
`}`

`func` `assertEqual``(``t` `*``testing``.``T``,` `expected` `Money``,` `actual` `Money``)` `{`
`if` `expected` `!=` `actual` `{`
`t``.``Errorf``(``"Expected  [%+v] Got: [%+v]"``,` `expected``,` `actual``)`
`}`
`}`

`type` `Money` `struct` `{`
`amount`   `float64`
`currency` `string`
`}`

`func` `(``m` `Money``)` `Times``(``multiplier` `int``)` `Money` `{`
`return` `Money``{``amount``:` `m``.``amount` `*` `float64``(``multiplier``),` `currency``:` `m``.``currency``}`
`}`

`func` `(``m` `Money``)` `Divide``(``divisor` `int``)` `Money` `{`
`return` `Money``{``amount``:` `m``.``amount` `/` `float64``(``divisor``),` `currency``:` `m``.``currency``}`
`}````

## JavaScript

Here’s how the `test_money.js` file looks at this point:

````const` `assert` `=` `require``(``'assert'``);`

`class` `Money` `{`
`constructor``(``amount``,` `currency``)` `{`
`this``.``amount` `=` `amount``;`
`this``.``currency` `=` `currency``;`
`}`

`times``(``multiplier``)` `{`
`return` `new` `Money``(``this``.``amount` `*` `multiplier``,` `this``.``currency``);`
`}`

`divide``(``divisor``)` `{`
`return` `new` `Money``(``this``.``amount` `/` `divisor``,` `this``.``currency``);`
`}`
`}`

`fiveDollars` `=` `new` `Money``(``5``,` `"USD"``);`
`tenDollars` `=` `new` `Money``(``10``,` `"USD"``);`
`assert``.``deepStrictEqual``(``fiveDollars``.``times``(``2``),` `tenDollars``);`

`tenEuros` `=` `new` `Money``(``10``,` `"EUR"``);`
`twentyEuros` `=` `new` `Money``(``20``,` `"EUR"``);`
`assert``.``deepStrictEqual``(``tenEuros``.``times``(``2``),` `twentyEuros``);`

`originalMoney` `=` `new` `Money``(``4002``,` `"KRW"``)`
`expectedMoneyAfterDivision` `=` `new` `Money``(``1000.5``,` `"KRW"``)`
`assert``.``deepStrictEqual``(``originalMoney``.``divide``(``4``),` `expectedMoneyAfterDivision``)````

## Python

Here’s how the `test_money.py` file looks right now:

````import` `unittest`

`class` `Money``:`
`def` `__init__``(``self``,` `amount``,` `currency``):`
`self``.``amount` `=` `amount`
`self``.``currency` `=` `currency`

`def` `times``(``self``,` `multiplier``):`
`return` `Money``(``self``.``amount` `*` `multiplier``,` `self``.``currency``)`

`def` `divide``(``self``,` `divisor``):`
`return` `Money``(``self``.``amount` `/` `divisor``,` `self``.``currency``)`

`def` `__eq__``(``self``,` `other``):`
`return` `self``.``amount` `==` `other``.``amount` `and` `self``.``currency` `==` `other``.``currency`

`class` `TestMoney``(``unittest``.``TestCase``):`
`def` `testMultiplicationInDollars``(``self``):`
`fiveDollars` `=` `Money``(``5``,` `"USD"``)`
`tenDollars` `=` `Money``(``10``,` `"USD"``)`
`self``.``assertEqual``(``tenDollars``,` `fiveDollars``.``times``(``2``))`

`def` `testMultiplicationInEuros``(``self``):`
`tenEuros` `=` `Money``(``10``,` `"EUR"``)`
`twentyEuros` `=` `Money``(``20``,` `"EUR"``)`
`self``.``assertEqual``(``twentyEuros``,` `tenEuros``.``times``(``2``))`

`def` `testDivision``(``self``):`
`originalMoney` `=` `Money``(``4002``,` `"KRW"``)`
`expectedMoneyAfterDivision` `=` `Money``(``1000.5``,` `"KRW"``)`
`self``.``assertEqual``(``expectedMoneyAfterDivision``,` `originalMoney``.``divide``(``4``))`

`if` `__name__` `==` `'__main__'``:`
`unittest``.``main``()````

1 ∀ x ≠ 0, i.e. as long as x isn’t zero … thank you, all the math teachers, for what you do!

2 The `===` operator tests whether both the values and the types of the two objects being compared are equal. See https://www.w3schools.com/nodejs/met_assert_deepstrictequal.asp

3 The ECMAScript standard defines a method as a “function that is the value of a property [of an object]” https://www.ecma-international.org/ecma-262/11.0/index.html#sec-method

4 The Python standard defines a method as “bound function objects”. That is, methods are always associated with objects, whereas functions are not. https://docs.python.org/3/c-api/method.html

• No Comment
..................Content has been hidden....................