Pippo's blog

it is all about software development

Moving to Robolectric 2

by filipesperandio

Android’s SDK is not a unit test enabler neither provide a fast way for developers to run unit tests. It is difficult to write and hard to run.

Robolectric fills a gap on android testing, more specifically on unit testing, that allows developers to get fast feedback and enables TDD. TDD is a hot topic these days and some of the concerns is when it comes to mocking.

By using RobolectricTestRunner class, developers get the benefit of having test doubles for android’s base classes and they can quickly run tests on the JVM, no need for the Dalvik’s VM.. This is true since version 1 of the framework although we still needed to many mocks to accomplish a test “mission”.

After the 2nd version of the framework, the embeded test doubles are much more realiable, mimicking device’s behavior much closer to our expectations and thus allowing for less mock dependent tests.

If you are in a project that uses Robolectric version 1, don’t be afraid of upgrading to the new version, it has many benefits. Keep in mind the library is not backwards compatible and adjustments will be required. The good news is that you can start having the benefits of the new version without having to migrate all your tests at once.

How?

The versions have different package naming structure, which means they are basically 2 different libraries and as so, you can add both to your project at the same time. Is that a good idea? Probably not for the long run, but it definitely is for the migration phase, which can last for a few weeks.

Pay attention to what packages to import when writing new tests and you will be very happy with the decision. If you have apklibs on your project, also keep an eye on the project.properties file, as the framework use it for reference and it can be the source of strange problems.

After that, just keep improving your test suite and remember how a test pyramid should look like.

Comments

AngularJS: Controller as … and closures

by filipesperandio

The ‘Controller as’ feature was introduced on AngularJS version 1.2. There is a good video from egghead.io on how to start using it.

This article also talks about this topic on the guide line #3. Take a few minutes and read that part of the article. Go ahead, I can wait.

Interesting, right? This feature helps a lot on your controller’s design and code maintainability, but let’s go one step further.

Let’s take the following controller and start to refactor it out:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 angular.module('app')
  .factory('MyResource', [ '$resource', function($resource) {
    return $resource('/dummyEndPoint');
  }])
  .controller('MainCtrl', [ '$scope', 'MyResource', function(scope, MyResource) {
    scope.save = function() {
      console.log(scope);
      var resource = {
        key1 : scope.key1,
        key2 : scope.key2
      };
      MyResource.save(resource, function() { scope.userSaved = true; });
    };
  }]);

… our html looks like this:

1
2
3
4
5
6
7
8
<body ng-app="app">
  <div ng-controller="MainCtrl">
    <input type="text" ng-model="key1" />
    <input type="text" ng-model="key2" />
    <button ng-click="save()"> Save </button>
    <i class="glyphicon glyphicon-ok" ng-show="userSaved"></i>
  </div>
</body>
  • Making the changes suggested by the article we end up with something like this:
1
2
3
4
5
6
7
8
<body ng-app="app">
  <div ng-controller="MainCtrl as main">
    <input type="text" ng-model="main.key1" />
    <input type="text" ng-model="main.key2" />
    <button ng-click="main.save()"> Save </button>
    <i class="glyphicon glyphicon-ok" ng-show="main.userSaved"></i>
  </div>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var MainCtrl = function(MyResource) {
  this.save = function() {
    var resource = {
      key1 : this.key1,
      key2 : this.key2
    };
    MyResource.save(resource, function() { this.userSaved = true; });
  };
};

angular.module('app')
  .factory('MyResource', [ '$resource', function($resource) {
    return $resource('/dummyEndPoint');
  }])
  .controller('MainCtrl', [ 'MyResource', MainCtrl ]);

This looks better already, we are not coupled to the given $scope object anymore. Decoupling is always good. This javascript object is also easier to test and it is clear that we are using angular to do the dependency injection. Hmmm, but now instead of a $scope soup, we have a this soup. Still not clear what is exposed and as the controller grows, things get uglier pretty quick.

  • At this point 2 things come to my mind:
    1. Start using Javascript Closures, I will talk more about it in a second.
    2. Tell the save method which object to save, allowing angular itself to build the object for us with small DOM change.
1
2
3
4
5
6
7
8
9
10
11
var MainCtrl = function(MyResource) {
  var userSaved = false;
  var save = function(resource) {
    MyResource.save(resource, function() { userSaved = true; });
  };

  return {
     save : save,
     userSaved : userSaved
  };
};
1
2
3
4
5
6
  <div ng-controller="MainCtrl as main">
    <input type="text" ng-model="resource.key1" />
    <input type="text" ng-model="resource.key2" />
    <button ng-click="main.save(resource)"> Save </button>
    <i class="glyphicon glyphicon-ok" ng-show="main.userSaved"></i>
  </div>

How does it look to you so far?

You can go further and wrap MyResource in a function making the controller even smaller. Taking logic out of your controller into another functions that can be injected into other controllers is a very good way to allow for code reusability on the angular world.

In my opinion, closures is the best way to write good javascript. It mixes a little of OO and functional programming in a way your code keep a very good structure. You have private attributes and methods/functions and the best: you avoid the $scope/this soup.

In the same way you saw the $scope soup before, abusing the reserved word this is also evil. Extending objects with prototype also seems unnatural for me, use it just when there is no other option. Javascript Closures make very clear what we are exposing and do a very good job with encapsulation.

Let me know your thoughts!

Comments

Lessons Learned With AngularJS

by filipesperandio

I love AngularJS. The framework allow me to design web applications in the way I think they should have been thought from the early days of the Web and Javacript. Personal feelings aside, the framework is showing itself as a enabler for better javascript’s architecture and code organization.

Learning Angular can be very challenging which make tips from many blog articles extremely welcome. But it is worth say that spending time trying things out is actually the way to master it.

In the next few days I will be posting more articles about lessons I learned from different teams, some I activily worked on, others I just took advantage from their pain.

Comments

Keep automating

by filipesperandio

When you start automating routines that you do more than a couple times, you tend to want to automate everything. Why? I think because it is challenging and funny. I am finding many opportunities to automate my routines these days and I am trying to keep the automation as part of my bash environment so I can reuse them as much as possible and have easy access to what I already did.

One of the challenges is to write code that you already know how to do in a different language like Ruby but to keep it in bash you have no clue.

The mix of languages bash can provide you with good support can enhance this experience a little, but don’t do too much outside of the bash world, otherwise you loose the benefits of doing so as functions to your terminal.

What I want to show you is this snippet where I can parse a JSON file and get the value I want directly from the terminal and being able to pipe it to another functions.

I was calling this google maps API, to retrieve latitude and lonngitude for an address, just like this:

1
2
url='maps.google.com/maps/api/geocode/json?sensor=false&address=Catedral+Metropolitana+de+Porto+Alegre+-+Rua+Esp%C3%ADrito+Santo,+Porto+Alegre,+Brazil&hl=en&ie=UTF8&sll=40.697299,-73.486176&sspn=0.754849,1.448822&oq=Catedral+Metropolitana+de+Porto+Alegre&hq=Catedral+Metropolitana+de+Porto+Alegre+-&hnear=R.+Esp%C3%ADrito+Santo+-+Centro,+Porto+Alegre+-+Rio+Grande+do+Sul,+90010-370,+Brazil'
http GET $url

Oh, and I use HTTPie as my default command line REST client ;-)

What this API return is a not-so-small JSON.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
{
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "Catedral Metropolitana de Porto Alegre",
               "short_name" : "Catedral Metropolitana de Porto Alegre",
               "types" : [ "point_of_interest", "establishment" ]
            },
            {
               "long_name" : "55",
               "short_name" : "55",
               "types" : [ "street_number" ]
            },
            {
               "long_name" : "Rua Espírito Santo",
               "short_name" : "R. Espírito Santo",
               "types" : [ "route" ]
            },
            {
               "long_name" : "Centro Historico",
               "short_name" : "Centro Historico",
               "types" : [ "sublocality", "political" ]
            },
            {
               "long_name" : "Porto Alegre",
               "short_name" : "Porto Alegre",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Rio Grande do Sul",
               "short_name" : "RS",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "Brazil",
               "short_name" : "BR",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "90010-370",
               "short_name" : "90010-370",
               "types" : [ "postal_code" ]
            }
         ],
         "formatted_address" : "Catedral Metropolitana de Porto Alegre - Rua Espírito Santo, 55 - Central, Porto Alegre - Rio Grande do Sul, 90010-370, Brazil",
         "geometry" : {
            "location" : {
               "lat" : -30.0335439,
               "lng" : -51.2295866
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : -30.0238836,
                  "lng" : -51.2135792
               },
               "southwest" : {
                  "lat" : -30.0432033,
                  "lng" : -51.245594
               }
            }
         },
         "types" : [ "place_of_worship", "point_of_interest", "establishment" ]
      }
   ],
   "status" : "OK"
}

… I just wanted latitude and longitude for the address on the url, and I wanted that information for a bunch of different addresses. Basicaly, I needed to navigate the JSON: first object on results array, than geometry node and get latitude/longitude fields from location subnode.

I came up with this function that allows me to do just that passing the nodes I want to navigate:

1
2
3
4
5
6
7
8
9
10
parse_json() {
  attrs=""
  for i in $*;
  do
    local regex='^[0-9]+$'
    local param=$([[ ${i} =~ ${regex} ]] && echo  ${i} || echo "'${i}'" )
    attrs=$attrs"[${param}]"
  done
  ruby -e "require 'json'; parsed = JSON.parse(STDIN.read)$attrs; puts parsed.to_json";
}

Having so I can store the JSON response in a variable to hit the API only once, and than reuse the JSON with diferent parsing arguments:

1
2
response=$(http GET $url)
echo $response | parse_json results 0 geometry

and still have a json result

1
{"location":{"lat":-30.0335439,"lng":-51.2295866},"location_type":"APPROXIMATE","viewport":{"northeast":{"lat":-30.0238836,"lng":-51.2135792},"southwest":{"lat":-30.0432033,"lng":-51.245594}}}

or narrow it down to location

1
echo $response | parse_json results 0 geometry location

almost there

1
{"lat":-30.0335439,"lng":-51.2295866}

and directly to one of the attributes we want

1
echo $response | parse_json results 0 geometry location lat

result

1
-30.0335439

Cool, hein?!

Remember I would like to be able to pipe the result to another command? So running the geometry filter again, with a one more command in the pipe:

1
echo $response | parse_json results 0 geometry | pretty_json

now with a pretty formatted json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
    "location": {
        "lat": -30.0335439,
        "lng": -51.2295866
    },
    "location_type": "APPROXIMATE",
    "viewport": {
        "northeast": {
            "lat": -30.0238836,
            "lng": -51.2135792
        },
        "southwest": {
            "lat": -30.0432033,
            "lng": -51.245594
        }
    }
}

pretty_json is an alias I have, which is basicly a call to a python function:

1
2
$ type pretty_json
pretty_json is aliased to `python -mjson.tool'

Being able to write small functions and glue them together in a pipe or reusing them in a loop can save me many manual work and also help me to learn bash more and more! I hope you do this kind of thing as well!

Comments

Showing Sinatra Routes

by filipesperandio

Just missed the rake routes from Rails in a Sinatra app. I didn’t want anything fancy, just a summary of the existing routes to play around. I came up with this:

1
2
3
4
5
6
7
8
9
10
11
require "sinatra/activerecord/rake"
require "./your_app"

task :routes  do
  ["GET", "POST", "PUT", "DELETE"].each do |verb|
    routes = Sinatra::Application.routes[verb] || []
    routes.as_json.flatten.each do |params|
      puts params["route_name"] if params.is_a? Hash
    end
  end
end

And then…

1
rake routes
Comments