I believe there is no right or wrong technology / library / framework to use when developing software except one that makes unit, integration and e2e testing easy to use.
People often ask me which of Laravel, Ruby on Rails, MEAN or MERN, Django, ExpressJS frameworks or stack is the best technology to develop web applications ?
I have a single answer — is the framework easy to write tests with?
Developing clean and testable codes has plenty of benefits for the programmer including:
- the documentation of logic and behaviour through description of test cases — which I prefer reading than going through codes that someone else had written or myself did 6 months ago
- writing alternatives test cases of scenarios we would otherwise not think of. For example, what happens if a value is null or undefined?
In the book Getting Real, the authors argue that it’s good to cater for an empty system because that’s the first impression the user gets. During our coding phase, we already have dummy values. Testers often ping me for broken features that works correctly on my machine. After importing their database and going through all the steps to reproduce the error, most of the time, I uncover null or undefined values as the main culprit.
Such unpleasant surprises occurring after long hours of coding is a waste of time and effort that I think can be mitigated with writing test cases (in most cases).
- you become more confident to refactor your codes without fearing regression
- your code base becomes easier to tingle with without worrying of breaking changes
- can write logic codes separately and independent of the current system, making it easier for us to focus on the implementation now and worry about the integration later
Of course, the biggest disadvantage is the time required to write down the tests. For developing a Minimum Viable Product (MVP), you want to iterate efficiently. In this regards, indeed, writing tests would be discouraged.
When prototyping with ever changing requirements, I try to postpone writing unit tests until the Project Manager or Owner freeze a set of features.
Developing clean testable codes makes it easier for any developer to promptly grasp the nature of the system or part of it by reading the tests. In fact, writing simple to debug codes with the aim of testing and code coverage, makes it easier for the developer to understand, change or debug. Unless your name is Linus Torvalds, Donald Knuth or Leslie Lamport, your codes will contain bugs.
I often underestimate the importance of code coverage when programming. I catch a piece of well written code that is not working. I lose time trying to understand the issue while in fact I did not test the else or else if condition that returns a value my function should be not returning. I tend to write conditions directly in if statements which makes it difficult for me to both test and debug.
I therefore try to separate the logic or conditions into a separate constant for better clarity.
Bonus : the clear variable name makes it easy to know what to expect.
I personally think the biggest reason to appreciate the use of Angular is thanks to its sublime command line tool ngcli. Even better is ng test for developing applications with plenty of business logic and validations. You can use a TDD approach.
By default, when you generate a component, class or service, it adds the spec file — unless you use the — spec=false flag. You can also disable it in the angular-cli.json file in the defaults section.
When you run ng test, the whole test suite automatically runs. No need to install anything apart from code coverage using Istanbul and other Karma plugins if needed. The process of running test suites is effortless.
With AngularJS, I had to painstakingly install Karma and it’s add-ons to run Jasmine and it’s additional matchers. I also had some configurations to make. It was a simple steps by steps process that initially took time— at the expense of my productivity. For whatever reason, this setup worked only on my PC and not on my colleagues’. With ng test, it works everywhere, irrespective of Linux, Windows or OSX.
If I want to manually add a spec file, I can add a .spec.ts file and Karma automatically picks it up just like RSpec.
Things I like with Angular :
- describe and it functions can be written with arrow function
- by default, ng test watches files for change and automatically run the suite — I find this Angular feature highly productive, as any change I do with the codes refreshes the tests
- I don’t need to manually add karma, karma jasmine and protractor libraries — Once I create a new app, they are all included
- Working on business logic and complex validation scenarios, I find the TDD approach highly effective ; it enables me to focus solely on the logic
How I write unit tests
Before writing the actual codes, I prepare a small set of data and try to solve the problem either on paper, in writing or using dry run tables.
Once done, I write an empty function with a set of parameters and a return value. I then write a unit test, passing the data set in the function and putting the expected result, which will fail at that point. I have written no logic yet.
Afterwards, I write the minimum logic to make the test pass — I focus on writing good enough codes. As I add more logic for different scenarios, I try to make the codes more readable and easy to debug.
For example, an array of objects to be sorted by date :
I need to check if the added date in a new object occurs after the existing dates in the list. I write down my expected outcome and add the test data (with minimum effort) before writing the codes.
Expected outcome :
If the sorted List has the new object as the last item, the test passes (returns true), otherwise it fails.
Unit Testing in Angular just works compared to it’s precedent. The ngcli tools provide a boost in productivity, enabling me to automate part of my workflow when developing Enterprise Applications or Enterprise Applications Integration tools.