AWS Velocity Series: Local development environment
The local development environment is where you make changes to the source code, edit configuration files, add images, and so on. You also want to run the app locally, execute the tests, and be able to debug your source code.
In this article you will learn how to setup a Node.js project from scratch with:
- Unit tests to cover internal functionality
- Code checks to get rid of typos and code smells early
- Acceptance tests to verify the end-user behavior
The Node.js app will offer an HTTP API to compute factorials. The concepts can be applied to any other programming language.
AWS Velocity Series
Most of our clients use AWS to reduce time-to-market following an agile approach. But AWS is only one part of the solution. In this article series, I show you how we help our clients to improve velocity: the time from idea to production. Discover all posts!
Let’s get started!
Setup project
You can follow step by step or get the full source code here: https://github.com/widdix/aws-velocity
First, create a folder for the new project. I assume that you use macOS or Linux running a terminal:
mkdir aws-velocity |
Within the new project folder, create folders for your app, infrastructure, deploy scripts, and your acceptance tests.
mkdir app |
The project structure should look like this now:
tree ../aws-velocity/ |
Let’s develop the app next.
A simple app
Now you need a simple app that you can use as an example. The app will be based on Node.js but the concepts will apply to all other programming languages. If you don’t have Node.js installed, visit nodejs.org.
cd app/ |
Now, create the app structure with the npm init
tool. The tool will ask you a bunch of questions, make sure to answer them as I did:
npm init |
And you need to install a few dependencies. express
is a popular web framework, jshint
is a code quality tool, and mocha
is a test framework:
npm install express@4.14.0 --save |
jshint
needs a little bit of configuration. Create a file .jshintrc
with the following content:
{ |
Create a file test/.jshintrc
with the following content:
{ |
Create a file .jshintignore
with the following content:
node_modules/** |
Now the app structure is done. Let’s see if the test command works:
npm test |
The tests fail because there are no tests. So let’s add some unit tests for the factorial implementation.
Create a file test/factorial.js
with the following content. The structure of the file is determined by the test framework mocha
. The important lines start with assert.equal
. Those lines contain actual test conditions that the implementation must satisfy:
; |
If you run npm test
again, the test still fail because there is no implementation yet. Let’s change that.
Create a file lib/factorial.js
with the following content. The factorial
implementation is recursive:
; |
Let’s see if the tests pass now by running npm test
.
Oh no, the implementation is missing some checks for edge cases. Change the file lib/factorial.js
accordingly:
; |
Now, wire express up to offer a HTTP endpoint for factorial computation. Create a file index.js
with the following content:
; |
You can now start the app locally:
node index.js |
In another terminal, execute curl
to make a HTTP request against your app:
curl http://localhost:3000/5 |
So far so good. It’s time to add an acceptance test.
cd .. |
Now, create the acceptance test structure. The acceptance test is an independent application also using Node.js. The npm init
command will setup the project. Make sure to configure it like I did:
npm init |
And again, you need to install a few dependencies. frisby
helps us to test REST APIs, jasmine
is yet another test framework, and jshint
will ensure code quality:
npm install frisby@0.8.5 --save |
jshint
needs some configuration. Create a file .jshintrc
with the following content:
{ |
Create a file .jshintignore
with the following content:
node_modules/** |
Now the app structure is created. Let’s see if the test command works:
npm test |
Everything is okay. Now you need to implement the acceptance test.
Create a file factorial_spec.js
(the file must end with _spec.js
!) with the following content. The structure is determined by frisby
, lines with a condition start with .expect
:
; |
To execute the acceptance tests against your locally running app (if you stopped the app, run node index.js
in a separate terminal), run:
ENDPOINT="http://localhost:3000" ./node_modules/.bin/jasmine-node . |
The application is done. You have unit tests, and you also have acceptance tests. The Important differences between the two are:
- Unit tests can run without spawning a web server
- Unit tests ensure that the factorial function returns the correct values
- Acceptance tests ensure that the REST API works as expected (e.g. as documented, or as it behaved before)
In the next article, you will learn how to setup the CI/CD pipeline for your new app.
Series
- Set the assembly line up
- Local development environment (you are here)
- CI/CD Pipeline as Code
- Running your application
- EC2 based app
a. Infrastructure
b. CI/CD Pipeline - Containerized ECS based app
a. Infrastructure
b. CI/CD Pipeline - Serverless app
- Summary
You can find the source code on GitHub.