Step 3 - Coding: calculator
Following Test-Driven Development (TDD) principles, we'll now code the software for the calculator software system.
For the purpose of demonstration, we use different programming languages to achieve the same goal.
Step 3.1 - Coding in C#: calculator
Step 3.2 - Coding in Java: calculator
Step 3.3 - Coding in JavaScript: calculator
Based on 'jest-try' at https://facebook.github.io/jest/
GitHub
As we created a repository called 'calculator' at the start of our use case, we will now create a branch for our code in JavaScript, as follows.
cd calculator
git branch javascript
Next, change our current branch to the 'javascript' branch.
git checkout javascript
From here on we will add and edit code for javascript in this javascript branch, in a newly created directory called javascript.
mkdir javascript
cd javascript
To see if Node is installed, type the below on your command line.
node -v
To see if Node Package Manager (NPM) is installed, type the below on your command line.
npm -v
Create a file `package.json` with the following content:
{ "devDependencies": { "babel-preset-env": "*", "jest": "*" }, "scripts": { "test": "jest" } }
Add the new file to git:
git add package.json
Create a file '.gitignore' with the following content:
/node_modules
Add the new file to git:
git add .gitignore
Create a file `calculator.js` with the following content:
// calculator.js function calculator() { return 'Hello World!'; } module.exports = calculator;
Add the new file to git:
git add calculator.js
Create a file `calculator.test.js` with the following content:
// calculator.test.js test('calls calculator to equal "Hello World!"', () => { const calculator = require('./calculator'); expect(calculator()).toBe('Hello World!'); });
Add the new file to git:
git add calculator.test.js
Run
npm installto install all entries of package.json.
Run
npm testand Jest will print a message alike this:
PASS .\calculator.test.js (10.266s) calls calculator to equal "Hello World!" (125ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 3.594s Ran all test suites.
Commit your changes:
git commit -m "first unit test"
And push your changes back to the 'javascript' branch
git push --set-upstream origin javascript
Check the status to verify that all has been committed:
git status
You just successfully wrote your first test using Jest!
This test used expect and toBe to test that two values were exactly identical. To learn about the other things that Jest can test, see Using Matchers.
Running from command line
You can run Jest directly from the CLI (if it's globally available in your PATH, e.g. by npm install -g jest) with variety of useful options.
If you'd like to learn more about running jest through the command line, take a look at the Jest CLI Options page.
PureScript
References: PureScript
Functional programming in JavaScript has its own disadvantages: JavaScript is verbose, untyped, and lacks powerful forms of abstraction. Unrestricted JavaScript code also makes equational reasoning very difficult.
PureScript is a programming language which aims to address these issues.
- It features lightweight syntax, which allows us to write very expressive code which is still clear and readable.
- It uses a rich type system to support powerful abstractions.
- It also generates fast, understandable code, which is important when interoperating with JavaScript, or other languages which compile to JavaScript.
PureScript is a functional, strongly typed, programming language that compiles down to JavaScript and/or Node.
We will re-factor the previous code to be using PureScript.
Install PureScript as follows:
npm install -g purescript
If PureScript has been installed successfully, you should see a response to the following command:
purs
Next, install the Pulp command line tool, and the Bower package manager.
npm install -g pulp bower
This will place the pulp and bower command line tools on your path. At this point, you will have all the tools needed to create our first PureScript code.
Read about Pulp at https://github.com/purescript-contrib/pulp
Start from inside the directory 'calculator'
Make sure you have the most up-to-date version from the repository by running the following command:
git branch javascript
Next, change our current branch to the 'javascript' branch.
git checkout javascript
Move inside the subdirectory 'javascript'.
Initiate the directory for PureScript using Pulp like so:
pulp init --force
It will have created the following files and directories:
bower_components/ src/ test/ .gitignore (replacing our original one) .purs-repl bower.json
The src directory will contain our source files, and the test directory will contain our tests.
When programming in Visual Studio Code, now would be a good time to install the extension 'PureScript Language Support' published by Nicholas Wolverson, a Syntax Highlighting for PureScript programming language.
Change the code of src/Main.purs to:
module Main where import Prelude import Control.Monad.Eff (Eff) import Control.Monad.Eff.Console (CONSOLE, log) main :: forall e. Eff (console :: CONSOLE | e) Unit main = do log "Hello World!"
Build and run the above code as follows:
pulp run
If all went well, files will have been compiled and put in the directory 'output'.
Also the application will have run and logged the following to the console:
Hello World!
Let's stage, commit and push this back to our javascript branch:
git add .
git commit -m 'first PureScript'
git push --set-upstream origin javascript
Check the status to verify that all has been committed:
git status
You just successfully wrote your first PureScript!
PureScript Modules
Another best practise is Component-Based Development (CBD).
To turn our PureScript code into modules (here: of type CommonJS, as used by NPM), all we need to do is execute the following command:
pulp build
The generated modules will be placed in the output directory by default. Each PureScript module will be compiled to its own CommonJS module, in its own subdirectory.
Let's stage, commit and push this back to our javascript branch:
git add .
git commit -m 'first PureScript CommonJS module'
git push --set-upstream origin javascript
Check the status to verify that all has been committed:
git status
You just successfully wrote your first PureScript CommonJS module!
Let's create a function 'message' inside our PureCode code that handles our 'Hello World!' message specifically.
Change src/Main.purs to the following:
module Main where import Prelude import Control.Monad.Eff (Eff) import Control.Monad.Eff.Console (CONSOLE, log) message :: forall t1. t1 -> t1 message s = s main :: forall e. Eff (console :: CONSOLE | e) Unit main = do log (message "Hello World!")
Now if we run the above code, we will see the same outcome, but the input has been passed to the 'message' function:
pulp run
To add modules to our project, we can do so as follows (for the Node.Process and Data.Array module):
bower install purescript-node-process --save
bower install purescript-arrays --save
The --save option causes the dependency to be added to the bower.json configuration file.
The purescript-node-process library sources should now be available in the bower_components subdirectory, and will be included when you compile your project.
Following Pure principles make the input visible, by requiring it as an input variable, like so:
module Main where import Prelude import Data.Array (drop) import Control.Monad.Eff (Eff) import Control.Monad.Eff.Console (CONSOLE, log) import Node.Process (PROCESS, argv) message :: forall t1. t1 -> t1 message s = s main :: forall e. Eff (console :: CONSOLE, process :: PROCESS | e) Unit main = do args <- argv log $ show (message (drop 2 args))
NOTE: In above code we have also added 'process :: PROCESS'
Now first build the code:
pulp build
Then run it, passing the input parameter 'Hello World!' as an argument:
pulp run -- 'Hello World!'
It will return:
'Hello World!'
Let's stage, commit and push this back to our javascript branch:
git add .
git commit -m 'first PureScript with visible input'
git push --set-upstream origin javascript
Check the status to verify that all has been committed:
git status
Unit Testing using PureScript Spec
For (unit) testing we can make use of the Test Framework for PureCode, called PureCode Spec
Install purescript-spec as a development dependency
bower install --save-dev purescript-spec
Now update the content of 'test/Main.purs' to:
module Test.Main where import Prelude import Control.Monad.Aff (delay) import Control.Monad.Eff (Eff) import Data.Time.Duration (Milliseconds(..)) import Test.Spec (pending, describe, it) import Test.Spec.Assertions (shouldEqual) import Test.Spec.Reporter.Console (consoleReporter) import Test.Spec.Runner (RunnerEffects, run) main :: Eff (RunnerEffects ()) Unit main = run [consoleReporter] do describe "purescript-spec" do describe "Attributes" do it "awesome" do let isAwesome = true isAwesome `shouldEqual` true pending "feature complete" describe "Features" do it "runs in NodeJS" $ pure unit it "runs in the browser" $ pure unit it "supports streaming reporters" $ pure unit it "supports async specs" do res <- delay (Milliseconds 100.0) *> pure "Alligator" res `shouldEqual` "Alligator" it "is PureScript 0.10.x compatible" $ pure unit
To run the test just execute the following command:
pulp test
The result from the test is this:
* Building project in C:\Users\user\Source\Repos\vanHeemstraSystems\calculator\javascript Compiling Test.Main * Build successful. * Running tests... purescript-spec » Attributes ✓︎ awesome ~ feature complete purescript-spec » Features ✓︎ runs in NodeJS ✓︎ runs in the browser ✓︎ supports streaming reporters ✓︎ supports async specs ✓︎ is PureScript 0.10.x compatible Summary 6/6 tests passed 1 test pending * Tests OK.
Let's stage, commit and push this back to our javascript branch:
git add .
git commit -m 'first PureScript Spec test'
git push --set-upstream origin javascript
Check the status to verify that all has been committed:
git status
You just successfully wrote your first PureScript Spec test!
To be continued ...