Sara

Context :

With my team I am developing a feature that can calculate weekly, monthly, yearly reports. After pulling the develop-branch on my computer, multiple tests went haywire. Tests for weekly reports had been added and those failed on my computer because of week numbers. After checking with all colleagues (Mac-users) and the Jenkins jobs that run all tests after commit (running on Unix) it seemed my Windows was the only one with failing tests.

So lets look at one of the failing tests :

        assertThat(row16.getCell(CONSOLIDATE_DATA_WEEK_COLUMN).getStringCellValue()).isEqualTo("2017-52");
        assertThat(row16.getCell(CONSOLIDATE_DATA_WEEK_COLUMN + 1).getNumericCellValue()).isEqualTo(7.0);
        assertThat(row17.getCell(CONSOLIDATE_DATA_WEEK_COLUMN).getStringCellValue()).isEqualTo("2017-53");
        assertThat(row17.getCell(CONSOLIDATE_DATA_WEEK_COLUMN + 1).getNumericCellValue()).isEqualTo(1.0);
        assertThat(row18.getCell(CONSOLIDATE_DATA_WEEK_COLUMN).getStringCellValue()).isEqualTo("2018-1");
        assertThat(row18.getCell(CONSOLIDATE_DATA_WEEK_COLUMN + 1).getNumericCellValue()).isEqualTo(6.0);
        assertThat(row19.getCell(CONSOLIDATE_DATA_WEEK_COLUMN).getStringCellValue()).isEqualTo("2018-2");
        assertThat(row19.getCell(CONSOLIDATE_DATA_WEEK_COLUMN + 1).getNumericCellValue()).isEqualTo(7.0);

Result :

        org.junit.ComparisonFailure: 
        Expected :"2017-53"
        Actual   :"2018-1"

What was happening :

Different countries have different time/date standards :

  • The calendar that is used.
  • The order in which the year, month and day are represented.
  • How weeks are identified (see seven-day week)
  • Whether written months are identified by name, by number (1–12), or by Roman numeral (I-XII).
  • Whether the 24-hour clock, 12-hour clock or 6-hour clock is used.
  • The punctuation used to separate elements in all-numeric dates and times.
  • Which days are considered the weekend.

My machine was using the settings from Great Britain, and my colleagues were using different settings. Meaning our week starts on different days(Sunday / Monday) and our year had a different amount of weeks due to this. My year only had 52 weeks. Their years consisted of an additional incomplete week with the last/first days of the year.

Iso standards : Wikipedia can give you a very dry explanation of how it all works, but just trying a few 31/12/YYYY on an ISO conform time converter can show you how it works.

If the week contains 4 or more days in year X, the week is in year X.Image description

Image description

How we fixed it :

Since we work for an international company we will have to implement a standard, and communicate this to all that use our API. We chose to use the settings from Great Britain, meaning that 2017 only has 52 weeks. Weeks should have 7 days, and should start on a Monday. Fully in line with the ISO standards.

To set the locale settings on the local servers and maven we used this :

         -Duser.language=en -Duser.country=GB

The tests were adapted to test if ISO standards and GB locale is used :

        assertThat(row2.getCell(CONSOLIDATE_DATA_WEEK_COLUMN).getStringCellValue()).isEqualTo("2017-38");
        assertThat(row2.getCell(CONSOLIDATE_DATA_WEEK_COLUMN + 1).getNumericCellValue()).isEqualTo(7.0);
        assertThat(row16.getCell(CONSOLIDATE_DATA_WEEK_COLUMN).getStringCellValue()).isEqualTo("2017-52");
        assertThat(row16.getCell(CONSOLIDATE_DATA_WEEK_COLUMN + 1).getNumericCellValue()).isEqualTo(7.0);
        assertThat(row17.getCell(CONSOLIDATE_DATA_WEEK_COLUMN).getStringCellValue()).isEqualTo("2018-1");
        assertThat(row17.getCell(CONSOLIDATE_DATA_WEEK_COLUMN + 1).getNumericCellValue()).isEqualTo(7.0);
        assertThat(row18.getCell(CONSOLIDATE_DATA_WEEK_COLUMN).getStringCellValue()).isEqualTo("2018-2");
        assertThat(row18.getCell(CONSOLIDATE_DATA_WEEK_COLUMN + 1).getNumericCellValue()).isEqualTo(7.0);

Tip of the day :

Because you are the only one having the bug, it's not a given that the issue is on your machine.

Because you are a minority, it does not mean you are wrong.

Sara

I spend 3 full days looking for a bug during my Spring 3 to Spring 4 migration at work, and finally found the issue:

Spring 3 will autowire beans on the ClassName,Spring 4 does this on the full.package.name.ClassName.

In the controller I was calling

Image description

and in my mapper was this :

Image description

The a.b.c.Languages was an interface, and unfortnuately the implementation, x.y.z.Languages is called the same.Making it very hard to find the issue.

The full stackOverflow post

Sara

Git has a strong commitment to backwards compatibility: many powerful features are hidden behind options rather than exposed as default behavior. Fortunately, Git also supports aliases, so you can create your own commands that do all manner of Git magic. Here’s a selection of the more useful (or at least entertaining) aliases defined in my .gitconfig:

Git Please

$ git config --global alias.please 'push --force-with-lease'

Git’s --force-with-lease option is far more polite than the --force option: it checks that your local copy of the ref that you’re overwriting is up-to-date before overwriting it. This indicates that you’ve at least fetched the changes you’re about to stomp. Since git push --force-with-lease is rather a lot to type out each time, I’ve created a polite alias for it: git please.

Git Commend

$ git config --global alias.commend 'commit --amend --no-edit

Ever commit and then immediately realize you’d forgotten to stage a file? Fret no more! git commend quietly tacks any staged files onto the last commit you created, re-using your existing commit message. So as long as you haven’t pushed yet, no-one will be the wiser.

$ git add Dockerfile
$ git commit -m ‘Update Bitbucket pipeline with new Docker image’
# (facepalm)
$ git add bitbucket-pipelines.yml
$ git commend

Git It

$ git config --global alias.it \
'!git init && git commit -m “root” --allow-empty'

The first commit of a repository can not be rebased like regular commits, so it’s good practice to create an empty commit as your repository root. git itboth initializes your repository and creates an empty root commit in one quick step. Next time you spin up a project, don’t just add it to version control: git it!

$ cd shiny-new-thing
$ git it
Initialized empty Git repository in /shiny-new-thing/.git/
[master (root-commit) efc9119] root

Git Staaash

$ git config --global alias.stsh 'stash --keep-index'
$ git config --global alias.staash 'stash --include-untracked'
$ git config --global alias.staaash 'stash --all'

git stash is one of the most delightful and useful Git commands. It takes any changes to tracked files in your work tree and stashes them away for later use, leaving you with a clean work tree to start hacking on something else. However if you’ve created any new files and haven’t yet staged them, git stash won’t touch them by default, leaving you with a dirty work tree. Similarly, the contents of untracked or ignored files are not stashed by default.

I’ve created a few handy aliases to handle different variations of git stash, based on which bits of your work tree you need to stash:

git stsh      # stash only unstaged changes to tracked files
git stash     # stash any changes to tracked files
git staash    # stash untracked and tracked files
git staaash   # stash ignored, untracked, and tracked fil

If in doubt, the long one (git staaash) will always restore your worktree to what looks like a fresh clone of your repository.

Git Merc

$ git config --global alias.merc 'merge --no-ff'

If you’re using a standard non-rebasing branching workflow, running a standard git merge to combine feature branches with the master is actually not ideal. With no options, git merge uses the --ff merge strategy, which will only create a merge commit if there are no new changes on the master branch, otherwise it simply “fast forwards” your master branch to point at the latest commit on your feature branch. Only sometimes creating a merge commit makes it tricky to reason about which code was developed on which branches when looking through your git history.

Image description

Git merc uses the --no-ff strategy, to always create a merge commit.

Image description

Incidentally, --no-ff is also what we use under the hood (by default) when merging pull requests in Bitbucket.

Git Grog

$ git config --global alias.grog 'log --graph --abbrev-commit
--decorate --all --format=format:"%C(bold blue)%h%C(reset)
- %C(bold cyan)%aD%C(dim white)
- %an%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n
- %C(white)%s%C(reset)"'

My git grog (or “graphical log”) alias has evolved over the years to the point where I’m no longer sure I understand exactly what it does. But it sure looks pretty:

Image description

Sara

Personal experience:

I have been working with TDD for the past two days and it is confusing me. There are a lot of reasons why this is the way to go, I am given a legacy project that no one has touched since 2011 and has no test-coverage whatsoever. To make sure I don't break everything I write tests before touching any of the code. Once the entire class is covered and has the proper fixtures, I can get started! Normally I would dive in the code but I am pair programming so ... adapting to my partner it is. He writes his tests first, and tries to write the minimal amount of code to get the test to pass. Sounds wonderful, but is completely against anything I have ever done. I have to temper myself not to go changing the code before my test is failing, yes failing. Just when that happens I am allowed to write code again.

I am having a hate love situation here. I love the security and the clean code. But tempering my code-enthusiastic fingers is not easy at all. Test driven development will take some time to get used to.

Image description

Sara

I used to keep a blog that was work / Ruby / general IT related and the blog motivated me to research new things. With this new blog I hope to engage myself more into discovering all cool new stuff thats out there. With lack of inspiration I will keep this KISS.

See you later.