Ensure High Code Quality in Flutter

Being one-man-army working on an app has some advantages. There is no deliberation about code formatting, libraries or frameworks used in the project. This is why migrating from react-native to Flutter was an easy decision, I just didn’t need to convince anyone apart from myself ;).

Of course all of those pros are also the cons. There is one that could prevent me from making bad decisions, checking in a bad code or braking old features while implementing new one. There is no one to deliberate about algorithmic, implementation and architectural choices in code review… you get the point?

There are some ways how some of those down sides may be overcome. For example writing unit and functional/integration tests is one of them. Code formatter and analyzer are another two.

Thankfully Flutter comes with all of the bells and whistles. There is flutter format, to automatically format your code, and flutter analyze to analyze code and enforce quality. Even more, both tools comes with awesome pre-build configurations that are used by Flutter team.

Unfortunately there is nothing that would automatically write test for you ;). But fortunately there are high quality and performant test frameworks that lets test your code on:

  • unit,
  • widget (functionality),
  • widget (presentation),
  • integration

levels.

One thing is to have the tools, but another is to use them… When you are part of a bigger team, someone will configure a build and CI/CD system for you, that probably will be running in the cloud. Or you can use something like CodeMagic… But in my situation I try to limit external services that I use with HabitChallenge.

One thing that I loved in my react-native times, was husky project. That lets you easily define and manage git hooks, especially pre-commit hook. This way I was able to run google typescript and unit tests before each commit.

Back in August 2019, there was nothing that may be compared to husky in dart/flutter ecosystem. So I decided to go with a general solution, the pre-commit project. Lets see how we can leverage pre-commit to ensure our code is properly formatted, doesn’t break any analyzer rules and do not break existing unit tests.

First of all we need to install pre-commit in our system, this is as simple as:
$ curl https://pre-commit.com/install-local.py | python –
or
$ brew install pre-commit

Secondly, we need to create a file called .pre-commit-config.yaml in our repository root with following content:

repos:
- repo: https://github.com/Cretezy/flutter-format-pre-commit
rev: 4a1df675bb74dea371c17934933e257e46f8dd98
hooks:
- id: flutter-format
- repo: https://github.com/dluksza/flutter-analyze-pre-commit
rev: 0bfdb7415bb2d02794a884bf2b763a92772001eb
hooks:
- id: flutter-analyze
- repo: https://github.com/dluksza/flutter-test-pre-commit
rev: ed4387d1e32d655e8f5cf58b410c9b4768f2950f
hooks:
- id: flutter-test

Finally run pre-commit install in the repository root and we are done!

OK, but what it is actually doing? Whenever you modify any dart file and decide to commit your changes to git repository, pre-commit will automatically run flutter format, flutter analyze and flutter test for you. If any of those command fails you will not be able to commit your changes. First you need to fix what have you broke then call git commit again. The good part is that when you modify any other file none of those commands are run!

This approach has two downsides. First of all, flutter format will automatically fix any formatting issues for you… but because of limitation in pre-commit you can’t modify files during pre-commit hook. This means that after files are properly formatted you need to run git commit again. Secondly, depending on your hardware, amount of code and number of unit tests it can take considerable amount of time to execute all those checks. You have been warned!

Hope you learned something 😉

Testing Flutter callbacks

We all know that we should test our code. Flutter makes this really easy with all of testing frameworks that are coming bundled with it. You can write unit tests, widget tests and UI test.


Testing callbacks are particularly tiring. I bet you seen code like this many times, even more, if you are testing your widgets, I’m almost sure you have written this kind of code.

testWidgets('callback', (WidgetTester tester) async {
  var pressed = false;
  final onPressed = () => pressed = true;

  await tester.pumpWidget(
    MaterialApp(
      home: FlatButton(
        child: Text('press me'),
        onPressed: onPressed,
      ),
    ),
  );

  await tester.tap(find.byType(FlatButton));

  expect(pressed, isTrue);
});

This pattern is fairly common. Declaring a bool flag that will be changed inside of callback function. No magic over here…

But writing this much code only to test simple callback hurts my programmer soul… Could it be done better?


Sure one can write helper function for this… And also another set of tests for this helper function. But as we all know, the best code is one that we didn’t wrote our selves.

Let me introduce you to Completer class, which is part of dart:async.
Test above could be now written as simply as:

testWidgets('callback', (WidgetTester tester) async {
  final completer = Completer<void>();

  await tester.pumpWidget(
    MaterialApp(
      home: FlatButton(
        child: Text('press me'),
        onPressed: completer.complete,
      ),
    ),
  );

  await tester.tap(find.byType(FlatButton));

  expect(completer.isCompleted, isTrue);
});

OK, but what if you would like to also verify what argument was given to the callback… No worries, Completer also have you covered:

testWidgets('callback', (WidgetTester tester) async {
  final value = 42;
  final completer = Completer<int>();

  await tester.pumpWidget(
    MaterialApp(
// imagine that FlatButton onPressed is called with 42 as a parameter
      home: FlatButton(
        child: Text('press me'),
        onPressed: completer.complete,
      ),
    ),
  );

  await tester.tap(find.byType(FlatButton));

  expect(completer.isCompleted, isTrue);
  expect(await completer.future, equals(value));
});

What if you have more than one argument in you callback. Unfortunately Completer will not help you here, you still need to write this tiring code from the first example. But how often do you have multiple arguments in your callbacks? One workaround is to wrap all of them into a helper class… This is your design choice…


Have you knew about Completer before? Did you used it already? Are you going to use this pattern in your tests? I’m looking forward for your answers in comment section.

How I endedup writing my first mobile app

At the time of writing it is already nine months since I’ve started my adventure with mobile app development and ReactNative in particular.

Before that I’ve wrote an simple Android “stopwatch with reporting over email” app for Megaron. I’ve also wrote full blown iOS app in Swift for my startup, that didn’t went live, although the app was decent! (Side note: as it usually is with tech startups run by tech people we didn’t found a market for it).

As you already know, HabitChallenge is not really my “first” mobile app, but it is first that went live and is actually used by plenty of people around the world.

The story starts back in July 2016, when I’ve broke my tibia bone… That means at least 3 months of lying down in the bed… no walking (at least not without crutches), no running, no going out… My first idea (actually second one, first was not to bother about it and live my normal life… how foolish I was) was “Let’s use this time productively and make as much as possible from it!”. That’s how I started thinking about my first publicly available mobile app.

Why mobile app? There were plenty of reasons:

  • I wanted to learn whole process from idea inception, through implementation, publishing the app, marketing it… and observing how it grows,
  • I always wanted to help other people, create something that would be usable for others,
  • Wanted to learn new technologies and explore this part of software development that I was not yet exposed to,
  • AppStore and Google Play are now huge markets, why not to participate in them,
  • Passive income is a big thing now, and mobile apps sounds like one of the possibilities.

OK, so it would be an mobile app… which platform? iOS or Android? Of course the answer is “both”. Since I was already familiar with development for both of them I know what to expect… and didn’t wanted to play with XML layout files for Android and Storyboard or XIB (which internally are also XML) for iOS; writing UI code manually was also not an option. Lucky on ClojureD conference I’ve heard about ReactNative and that was my weapon of choice 😉

I’ve already said why and how… but “what” is still an open question. It shouldn’t be something big, nor buyer-seller type of app. It should some kind of utility app… or productivity…

Back then I was using HabitLoop to track my habits. It was not the nicest looking app, but it is open sourced has decent set of features and only available on Android. “Yeah! Let’s write yet another habit tracking app!” was my thought… “But it should have some ‘twist’, so that it won’t be a simple clone…”.

At that point I’ve started listing features and picking what will be included in first release (aka. MVP). In about two days I had listed everything, write it down, decided and commit for it.

The first version of HabitChallenge app had:

  • awesome UI and UX (that means I need to find someone to do it for me),
  • habit that can repeat on particular day of week,
  • habit can repeat multiple times per day (eg. drink 7 glasses of water),
  • habit can have multiple reminders,
  • no ads,
  • free version with limits for number of habits, reminders and repetition during the day,
  • in app purchase for the Pro version.

HabitChallenge featured image

Estimated time: 4 weeks, actual time spend: 9 weeks. The first version of HabitChallenge was available for install on AppStore and Google Play on 13th of October 2016.

Just recently HabitChallenge was installed over 10 000 times on Google Play (it took about 5 months to get there). It is used all over the world (although it only supports only Polish and English) and the “twist”, the “killer feature” is still not implemented yet… and I’m still working it 😉

If you manage to read so far… that’s the end 🙂 Please give HabitChallenge a try and if you like it give it 5 starts on Google Play and AppStore 🙂

How to run multiple WordPress installations on one NGINX?

If you ever would like to run multiple WordPress installations on one NGINX server and sharing one domain name. Also you would like to have nice urls like /%catetgory%/%postnname%/ on both of them. You better do not do it in the root configuration block like this:

location / {
  try_files $uri $uri/ /index.php?$args /another-nestetd-wp/index.php?$args;
}

Of course this will work… but as a side effect posts from /another-nested-wp/ will be leaking into main blog RSS feed. Trust me 🙂 I’ve only found out about this thanks to JVM Bloggers and my colleagues asking me wether my site was hacked 😀

Some things one need to learn the hard way.

Nevertheless, proper NGNIX, configuration should be done for /another-nested-wp/ (not root node):

location /another-nested-wp/ {
  try_files $uri $uri/ /another-nested-wp/index.php?$args;
}

This way both blogs shouldn’t interfere with each other. And both can use nice urls 😉

One again many thanks to the community from JVM Bloggers for quick information about this (self)hack 😉

Gerrit Hackathon at Google HQ… next one is coming

Gerrit Hackathon 2015Gerrit Hackathon 2015

As always after the Gerrit User Summit, a Gerrit hackathon took place.
This time it was a five days event (9-11 November 2015), where members of the Gerrit community could work together, fully focused on making Gerrit a better software.
2015 edition gathered 15 participants from various companies like Google, SAP, Sony Mobile, Qualcomm, OpenStack, Axis Communications, Gerritforge and of course CollabNet.
Hackathons are really intensive periods of time for Gerrit project: over 400 patches were merged, three releases (2.11.5 and two release candidates of 2.12) were performed, countless number of open changes and patchsets were pushed for review.
This blog post summarizes work done during that period of time, showcasing new features upcomming in 2.13 and 3.0 release.

Gerrit metrics

Gerrit Metrics in Grafana2Gerrit Metrics in Grafana2

If you are responsible for running mission critical software for your organization, you must know how important monitoring and metrics are. How important it is to get fine grained information about the application performance. It is simply not enough to know whether it is up and running but also what is the overall shape of it.
This kind of information is especially critical when users start complaining “Gerrit is slow”.
From time to time such complaints arrive also to our team in Potsdam, then we use Splunk to analyze the load based on Gerrit logs and give our recommendations how to tweak Gerrit. Based on such cases our Gerrit Performance Cheatsheet was composed meuh7iu.
Starting from Gerrit 2.13 we will have a new tool in our toolbox! Internal Gerrit metrics!
DropWizard Metrics library is used as internal engine. Gerrit exposes over 1300 metrics about crucial internals e.g. http server response time, git receive pack, git counting objects, cache sizes, etc….
What is even more awesome, plugins can report their own metrics using the core API. This way replication plugin for 2.13 will report time taken to replicate repository data to various locations.
One thing is to collect metrics, the other is to store them. For this purpose three new plugins were created: metrics-reporter-elasticsearch, metrics-reporter-graphite and metrics-reporter-jmx. This gives possibility to plug Gerrit in into already existing infrastructure.

Hooks as plugins for core events

There are two ways in Gerrit how one can be notified about git operation related events. One is via event mechanism and another via Gerrit hooks. Both provide almost identical functionality making deciding on implementing one of them harder.

During our hackathon work was started to extract hooks mechanism into plugins that would listen to core Gerrit events.

This work is still ongoing, but once it gets finished one that want to run server side hooks must install the Gerrit hook plugin.

gwtorm can be used from plugins

You may be wondering what is the gwtorm. This is a library written for Gerrit project to access relational databases. It is a lightweight method of connecting your Java application to multiple different DB backends. Initially it was meant to be used only by GWT based applications (hence gwt prefix in its name), but currently it can be used by any Java application.

Why to use gwtorm in plugin? Well if you don’t want to modify Gerrit schema (which is highly discouraged) to store your plugin data and want to support many SQL dialects out of the box, gwtorm is the way to go.

The first plugin that will use this library is gerrit-ci-plugin.

Gerrit 2.11.5 and 2.12-rc

Gerrit releases don’t happen too often. Some time we had to wait long months (and over 1000 commits) to get new stable version of Gerrit. Usually just before the hackathon a release candidate of new stable version is cut from the master branch.

During this year’s hackathon we got three releases! One was a service release for 2.11 (updated release notes) branch containing fixes for javascript clipboard, styling, commit validation error handling.

Apart from service release two release candidates were published for Gerrit 2.12.

Submit whole topic dialog

Gerrit 2.12 changes how patches are submitted to the repository after code review. In all previous versions there was so called “merge queue” which was responsible for submitting patches in the right order. If particular change was submitted but its ancestors were still under review it ended up in a special state “submitted, merge pending”.

In 2.12 changes arranged in a branch (one change depending on the other) can be submitted at once by single click on the submit button on the topmost change.

Additionally new feature called ‘submit whole topic’ was added. It enables submission of changes that share the same topic. This can be done across multiple projects and branches.

One thing that struck us when this feature was presented during Gerrit User Summit was change in the semantic of Gerrit ‘topic’. Before 2.12 topics were only metadata that could have been freely added and removed. Plus there was possibility to search for changes that share the same topic. Starting from  2.12 setting a topic on changes will change how they are submitted. In some rare cases one can submit changes of others or block them because of a change not visible to all is still waiting for being reviewed.

To make submitting more verbose during the transition period, a submit dialog was proposed. It pops up after clicking on the submit button only when changes from the same topic would be submitted. It presents the list of changes submitted in a topic and without it, so that the submitter can choose whether to just merge the change in question or all changes of the same topic.

CI verification

Some time ago a Diffy build bot was introduced to verify changes pushed to gerrit-review.googlesource.com, but after some time it become unreliable, often was simply not verifying because it was not running.
Now there is new verifier in the picture. Based on proven gerrit-trigger-plugin custom REST API pooling strategy and Jenkins tandem. It is kindly hosted by the GerritForge. Long life to new GerritForge CI bot!

NoteDB

NoteDB is the defining feature of Gerrit 3.0. It will replace “conventional” database system and store everything inside git repositories. All the data that is currently stored in SQL DB will be moved to git repositories. Review related information will be stored in the particular repository using git-notes and special refs. User data will be moved to dedicated repository.
During the hackathon further steps into achieving the goal of removing the dependency from SQL DB were performed, some integration tests were fixed plus NoteDB tests were enabled  as a part of verification job.

New Gerrit UI with Polymer

Last but not least, the new Polymer based WEB UI for Gerrit was initially announced and integrated into Gerrit’s build process.

During the Gerrit User Summit, Google has presented the draft of a new Gerrit WEB UI. This time it is written using Polymer framework, which is a new JavaScript UI design framework from Google.

The new WEB UI will be fully written in JavaScript, making it easier for UI/UX designers to modify and faster to develop and compile.

As I mentioned before, during hackathon PolyGerrit project was integrated into standard Gerrit build system. It requires teaching Buck how to deal with javascript and its dependencies.

What is next?

Next is the Berlin Gerrit Hackathon in 2016. We’ve open a poll to gather input from the community about preferable date between 22nd of February and 25th of March 2016. Please participate if you would like to join us and hack Gerrit in Berlin 🙂