2014 m. rugpjūčio 30 d., šeštadienis

Does mocking breaks encapsulation ?

Recently I had a discussion regarding unit testing and specifically about how mocking dependencies violates encapsulation. In other words i've been told that your tests should not fail if implementation of unit changes. You just test if given input results to expected output and what dependencies are used there and how, should not be included in your unit tests.

I do not agree with this. I believe unit tests should explain how unit will behave in certain conditions. These conditions can be created only by mocking dependencies. Your tests are like documentation which describes the logic of the unit and what were requirements at the time it was created. Now if your unit implementation will change and dependencies will be used differently or different dependencies will be used, but output of the unit will still be the same, you will have your unit tests that describes dependencies usage failing and only test which asserts output will still be passing. Is this ok ? Does this breaks encapsulation ? Should you be fixing your tests when implementation changes ? I'd say it does not break it and it is ok to change unit test along with refactored unit.

As I understand it, encapsulation allows you to hide the internals of the object and prevent code that is using that object to set it in some invalid or inconsistent state. Over exposed public methods we control access to our object and in this way we protect it from outside world. But does this means that unit tests should not know HOW that public method is working ? What are possible execution paths ? What is the logic of it ?

For me, unit test is a piece of code which is interested in internals of method and by writing tests we make sure that logic inside that method works as we expect. Unit test code is not the same as production code which uses that public method. Production code does depend only on the provided contract, but it does not care about internals and implementation. Besides with unit test we are not changing how our unit is working, all we do is just we change how dependencies behave and we do assert how and with what data those are being called.

Of course if you do not use inversion of control and your dependencies are created in private methods then you will be using reflection to mock these and that is changing internals of your unit. But I would still go for it and would mock it, because I want to be sure that my method works as expected in given conditions. And afterwords I would just refactor it so that dependencies could be injected.

My conclusion on this would be that mocking dependencies to test possible execution paths and tie up your tests to implementation details is ok and no encapsulation is violated here (with exception mentioned above). Because changing implementation is like changing documentation of your method and that should be mirrored on your unit tests.

2014 m. rugpjūčio 17 d., sekmadienis

AwareUnit CmsInn tutorial - the one about labels, languages and images

Overview

CmsInn is a Meteor package that allows you to add CMS functionality for your project. This CMS is different from others in a sense that it allows you to pick which bits of your application can be edited over this CMS package. It's not like you will have to use CmsInn to create your application but instead you will dedicate to CmsInn to handle some of CMS functionality. For example perhaps you just want your app to have multiple languages and be able to translate texts. So you can just hook in CmsInn translations plugin in your app and do the rest by yourself. Same principle applies to the rest of the CmsInn features.
Main purpose of CmsInn is to allow developer to choose what he wants to use from offered functionality and what he will do by himself.
This tutorial will focus on how to create a fresh Meteor project and integrate basic features of CmsInn package.

Getting started

I assume that you have Meteor and Meteorite installed already. If not please read their docs on how to do that.
Now first of all let's create a new meteor project and add CmsInn package.
mrt create cms-test-prj
mrt add au-cmsinn
mrt remove insecure
mrt remove autopublish
Once project is created delete all files in root directory except 'smart.json'. Then create `init.js` file in your projects root folder with this content:
if (Meteor.isClient) {
    CmsInn.configure({
        layoutTemplate: 'layout'
    });
}
if (Meteor.isServer) {
    CmsInn.configure({
        plugins: {
            versioning:{
                insecure : true
            }
        }
    });
}

We call configure once on client and once on server. On client we configure which layout should be used and call on server sets 'insecure' to true and that makes CmsInn to publish all content. Bit later we will configure roles which are used for authorization. For now we will enable `insecure` mode which allows us to skip roles configuration.
Reason why we need to set layout is that CmsInn comes with Iron-Router and configures it on this call. Iron-router is used to handle routing to pages that you will create dynamically. It will be explained in next post.
Now let's create `index.html` file in projects root directory with this content:
<head>
    <title></title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    <meta name="description" content="">
    <meta name="author" content="">
</head>
<body></body>
<template name="layout">
    {{> cmsinn_controls_left}}
</template>
Run your meteor project and if you will check your page you will see that control panel of CMS has appeared. This control panel is your dashboard and it is used to manage your app content. Each button has it's own purpose. We will go through those in details now.

Content editor

First and the most important feature i'd say is actual content editing. With CmsInn in no time you can enable this for selected bits of your application.
To do that we have to define in our templates which parts of our website should be editable. So in `index.html` file edit your layout template like this:
<template name="layout">
    {{> cmsinn_controls_left}}
    <div class="section">
        <div class="container">
            <div class="row">
                <div class="col-lg-4 col-md-4">
                    <h3 data-au-label="brand">{{c 'brand'}}</h3>
                </div>
            </div>
        </div>
    </div>
</template>
Now after page refreshes if you will click on first button in the control panel you will notice that '<h3>' element becomes editable. And this applies to all elements in your page that has attribute 'data-au-label'. All these elements will have a popup with input field on mouseover and you will be able to change the content and then to output it with a help of '{{c <ID_OF_LABEL>}}' helper.

What is cool about it is that you edit content in selected language. So essentially it is also a translations mode because it allows you to translate content in all languages that you will create. We will see bit later how easy it is to add new language.

So in general whenever you need to make content editable you just add an attribute on element and the rest is handled by CmsInn.

Let's add label which will bring rich text editor. Update your template as follows:
<template name="layout">
...
   <h3 data-au-label="brand">{{c 'brand'}}</h3>
   <p data-type="wysihtml5" data-au-label="brand_description">{{{c 'brand_description'}}}</p>
...              
</template>
You will see that rich text editor appears instead of simple input. This happens because we have changed the type of editor. We have added new 'data-type' attribute to a '<p>' element which allows us to provide different type of editor. CmsInn uses x-editable so idea is that you will be able to define any type that x-editable supports.
One thing to notice is that for rich text you have to use `{{{}}}` triple brackets so that output would not be escaped.

Once you have added new element after page refreshes click on 'Translations edit mode' (same first button) and you will see editor popping up. Change content and save it. After refresh you will see your content loaded.

Now let's add 'date' type field. Update your template as follows:
<template name="layout">
...
   <h3 data-au-label="brand">{{c 'brand'}}</h3>
   <p data-type="wysihtml5" data-au-label="brand_description">{{{c 'brand_description'}}}</p>
   <span data-type="date" data-au-label="brand_created">{{c 'brand_created'}}</span>
...
</template>
After page refresh you will get date selector on mouseover.
Now when you know how to make your content editable let's move on to add couple of languages.

Languages

Adding new language is pretty easy. Somewhere in your template you will have a language selector HTML element. So what you have to do is add 'data-au-locale' attribute on those elements. Then CmsInn will bring in a locale selector and you will be able to attach language to it.
For example update your layout template as follows:
<template name="layout">
...
    <hr/>
    <div class="section">
        <div class="container">
            <div class="row">
                <div class="col-lg-4 col-md-4">
                <a data-au-locale="english" href="#" data-au-label="english">{{c 'english'}}</a> |
                <a data-au-locale="lithuanian" href="#" data-au-label="lithuanian">{{c 'lithuanian'}}</a>
                </div>
            </div>
        </div>
    </div>
</template>
When you will toggle on "Languages edit mode" locale selector UI will appear. Click 5th button from top and you will see a blue dash border around those two elements. Move mouse over it and select locale you want to be switched on when this element is clicked.
Once you have attached locale refresh the page and you will notice that content changes when you switch between languages. Try to edit content in both locales and you will see that content for labels will be loaded depending on selected locale.
Once you switch to language that does not have translations you will notice that labels has content from other language and that in '()' it will show in which language you are currently in.
You can add as many languages as you want. Workflow to do that is the same.

Images

Now let's see how we can make images on our website editable. We have few dependencies here to install first.

For image handling this package uses gm package. So first download and install GraphicsMagick or ImageMagick. In Mac OS X, you can simply use Homebrew and do:
brew install imagemagick
brew install graphicsmagick
Once that is done update your layout HTML like this:
<template name="layout">
...
    <hr/>
    <img data-au-image="logo" src="{{loadImg 'logo' '400x400'}}" />
</template> 
Now go to website and toggle on 'Image mode' which is fourth button from top. Image element you have just added will get a blue border now. Just drag and drop some image from your desktop in that marked area. In a moment your image will be displayed in a size you have requested it. In this case '400x400'. You can change the size in template and you will see that image will be automatically resized next time you will refresh the page.

Conclusion

This post covers just the basic part of CmsInn. My goal was to show the idea and how it supposed to be integrated in fresh project. In next post I will cover the remaining features - "Navigation", "Records", "Sorting", "Deleting", "Publishing" that has not been explained here. There is some documentation on project's GitHb page.