Our Blog.

Expert thoughts from our software developers and design leaders.

  • Larry Morales on November 6, 2019

    A fridge contains drinks

    Continue Reading
  • Manuel Perez on October 10, 2019

    How to mock an external service for tests in GO

    From my experience as a software developer, an issue that I have dealt when building an application are the dependencies for external services. A test with external dependencies where you don’t have much control can fail if there is a change in the service and the outcome is not the expected, with this in mind, we need to ensure the non-dependence of external services when running our tests. The most effective way to do this is mocking those dependencies.

    In this post, I will focus on the functional tests of an application. I will also talk about how to mock an external service to not rely on it when running our functional tests.

    To explain how to mock an external service, I’ll walk you step by step through an example.

    Let’s say that we have an endpoint, that is using a third-party package called holidays that is making HTTP requests to an external service to get such holidays.

    # /actions/holidays.go
    package actions
    
    import (
        "time"
        "github.com/somebody/holidays"
        "github.com/somebody/holidays/filters"
    )
    
    func Holidays(w http.ResponseWriter, r *http.Request) {
        currentMonth := int(time.Now().Month())
    
        filters := filters.Params{
            Months: []int{currentMonth}
        }
        
        message := "There are not holidays"
        
        days, _ := holidays.GetHolidays(filters)
        if len(days) > 0 {
            message = fmt.Sprintf("Holidays for this month: %v", days)
        }
    
        fmt.Fprintf(w, message)
    }
    

    Step 1: Separating the external service logic from our business logic.

    The environment where we executed the tests should not depend on any external service. Since we’re only testing the functionalities of our application and how it behaves with any input, regarding external services, we only care about the outcome of it.

    To achieve a higher level of control over our tests, we need to move all the holidays-service-logic to a separate package.

    # /lib/holidays/holidays.go
    package holidays
    
    import (
        "github.com/somebody/holidays"
        "github.com/somebody/holidays/filters"
    )
    
    func Holidays(months []int) ([]int, error) {
        filters := filters.Params{
            Months: months
        }
        days, err := holidays.GetHolidays(filters)
    
        return days, err
    }
    

    Once the logic is separated we have to make sure we must call the external service using the new package from our actions package.

    # /actions/holidays.go
    import (
        "project/lib/holidays"
    )
    
    func Holidays(w http.ResponseWriter, r *http.Request) {
        ...
        days, _ := holidays.Holidays(months)
        ...
    }
    

    Step 2: Abstracting the use of the service through an interface.

    So far, this solution doesn’t solve the problem, the tests are still executing all the holidays-service-logic so we are still making HTTP requests that we don’t want to be made. We have to do something else.

    To mock the external service, we can abstract all its logic within an interface which we can implement elsewhere and use it by our functional tests, returning the outcome we need to test the behavior of our application.

    Here is how such an interface would look like:

    # /lib/holidays/holidays.go
    package holidays
    
    import (
        "github.com/somebody/holidays"
        "github.com/somebody/holidays/filters"
    )
    
    var Client ServiceFunctions = holidaysService{}
    
    type ServiceFunctions interface {
        Holidays([]int) ([]int, error)
    }
    
    type holidaysService struct{}
    
    func (hs holidaysService) Holidays(months []int) ([]int, error) {
        filters := filters.Params{
            Months: months
        }
        days, err := holidays.GetHolidays(filters)
        return days, err
    }
    

    Client is a global variable that receives as value any type that implements the ServiceFunctions interface, by default it uses holidaysService{} who communicate with the external service but on the side of the tests, we can update its value with another type that implements the same interface by returning the outcome we want.

    var Client ServiceFunctions = holidaysService{}
    

    We have to make a change in the way of calling the external service, now it would be through our Client global variable.

    # /actions/holidays.go
    
    func Holidays(w http.ResponseWriter, r *http.Request) {
        ...
        days, _ := holidays.Client.Holidays(months)
        ...
    }
    

    Step 3: Create the mock of our interface.

    Once all the functions of the holidays-service are abstracted, we need to create another type that implements the same interface with the intent to use it as a dummy object for our tests. In this case, our new Holidays function we’ll return a list of hard-coded days and an error.

    # /lib/holidays/holidays_mock.go
    package holidays
    
    var (
        Days []int{}
        HolidaysError error
    )
    
    type ServiceFuncMock struct{}
    
    func (sfm ServiceFuncMock) Holidays(months []int) ([]int, error) {
        return Days, HolidaysError
    }
    

    We can make this interface as dynamic as we want, we can return different values in order to test how our application behaves.

    Step 4: How to use the mock?

    Given our test is still depending on external service. We will replace the holidays-service call by the simulation we created.

    We assign an instance from our mock to the Client variable we defined before:

    holidays.Client = holidays.ServiceFuncMock{}
    

    Here we are setting the value for our Client, we’re using the ServiceFuncMock "test interface" as the default interface.

    Here is an example of how to test our application with no external dependencies.

    Test 1: In this test, we simulate the response from the holiday-service with an empty list of holidays and our application should display “There are not holidays”.

    # /actions/holidays_test.go
    package actions
    
    import (
        ...
        "project/lib/holidays"
    )
    
    func Test_Holidays_Without_Days(t *testing.T) {
        holidays.Client = holidays.ServiceFuncMock{}
    
        req, _ := http.NewRequest("GET", "/holidays", nil)
        ...
    
        assert.Contains(t, res.Body.String(), "There are not holidays")
    }
    

    Test 2: In this case, we set a different response for the days that the Holidays function will return.

    # /actions/holidays_test.go
    
    ...
    
    func Test_Holidays_With_Days(t *testing.T) {
        holidays.Client = holidays.ServiceFuncMock{}
        holidays.Days = []int{1, 3, 5}
    
        req, _ := http.NewRequest("GET", "/holidays", nil)
        ...
    
        assert.Contains(t, res.Body.String(), "holidays for this month")
        assert.Contains(t, res.Body.String(), "1")
        assert.Contains(t, res.Body.String(), "3")
        assert.Contains(t, res.Body.String(), "5")
    }
    

    As you can see, mocking external services is an effective method when testing our application’s features that require the use of them. This method also serves us well to decrease the coupling of our application regarding external services.

    Thanks a lot for reading! Keep on learning and coding!

    Continue Reading
  • Efren Ospino on October 3, 2019

    How's it like to write an Android app in 2019?

    First, for Java developers only

    As Android developers, there are many ways to write an app and get tired of seeing how the lack of features of the Java (Java6 by default) platform embedded in the Android SDK slows the coding process. Notice that Java6 last public update dates from 2013 and that is the version you are expected to use on Android development with Java. You can use Java8 language features but most of the powerful features can only be used in devices that are running Android 7.0 Nougat (API 24).

    By May 7, 2019, Android 10 not released yet, there was a total close to 41.9% devices running Android OS prior Nougat out of 2.5 billion active devices.

    alt text

    This means that all of those devices are not able to take advantage of most of the Java8 features like functional interfaces, Stream API, Concurrency and IO enhancements and more. And without mentioning any of the post Java8 releases (Java13 is already here).

    Hello Kotlin

    JetBrains, the company that develops IntelliJ IDEA (a powerful Java IDE and what Android Studio is based on), back in 2011 began developing Kotlin, a new cross-platform, general-purpose programming language that interoperates with Java and the JVM. They addressed some issues that the Java Programming Language has and made a good job of giving Kotlin the ability to run well enough to develop Android applications. This huge effort won some interest in the community and within the Android development team making it a topic of conversation between Android developers a few years ago.

    People got started with Kotlin by writing new features and apps from scratch using a couple of Gradle plugins that JetBrains developed but there was no official support from the Android team at Google. At I/O 2017, it was announced that Kotlin was going to be a first-class language for Android development together with Java and C++. They were not replacing anything at this point but it was a big step the fact that a new language has been added officially and allowed developers to write Kotlin code in Android Studio IDE in the easiest way.

    2 years later, at I/O 2019, it was announced Kotlin at their most preferred language inside the Android team which meant they will opt the Kotlin-first approach and all the new Android platform support features were going to be developed thinking in Kotlin developers. This way Google has reinforced their support for Kotlin and encouraged developers to write more applications using Kotlin.

    Nowadays, most of the Android developer documentation by Google is offered in Kotlin with code examples. New support libraries, Android KTX and more libraries are being released as well in Kotlin. Apps and Open Source libraries are written in Kotlin more and more, and the community has accepted their use.

    You may ask, what’s next?

    Besides the Java Programming Language is a powerful language and there is no doubt about it, excellent apps can be written by using it as the main language on your Android project but you should get started with Kotlin. It is a modern programming language and it has features that you will want to appreciate when writing your Android app. Today, there is the chance to work with it and it is not a bad idea to start playing with it.

    At Wawandco we love Kotlin! And it has been a nice ride since we started using it the last year. We became more productive and we did learn it fast. We encourage you to learn Kotlin if you haven’t already! There are many advantages that you win by using this programming language and it is worthy of giving it a try.

    Continue Reading
  • Antonio Pagano on September 28, 2019

    Custom Web Fonts in Buffalo

    In certain situations the site or app you’re building uses fonts that are not hosted in a CDN. The font is not in Google fonts, and is not in Adobe Fonts or other provider.

    You may be given at that point a set of OTF, TTF and WOFF files. But what do do then? How do you integrate those font files in your Buffalo app?. After all, you want your frontend to look as closer to what your designer has put together, And we all know that fonts matter.

    What to do?

    Assuming you are in your Buffalo app folder, take a look at the assets sub-folder.

    - assets
      > css
      > images
      > js
    

    Nothing there says fonts, right?.

    Brief context on the buffalo assets build process

    Buffalo bases its assets build in Webpack. It compiles Javascript using Webpack tools like Babel, and processes the SASS/SCSS using node-sass.

    That leaves images alone, Right?

    Images are copied into the public/assets/images folder. And like this, all other folders or files that are not CSS or Javascript get copied to the public/assets folder.

    At build time, the public folder is filled with the results of the assets compilation and then is packed into the app binary, with Packr. But Packr is a whole complete (and long) separate topic.

    Our solution

    Now that we know how files in the assets folder are processed and packed into the binary, you may know what’s coming up.

    We need to create another folder called fonts inside the assets one.

    - assets
      > css
      - fonts // Like this!
        * myFont.woff
        * myFont.ttf
        * myFont.otf
      > images
      > js
    

    But that’s not all. Until this we’ve only ensured that the fonts make it to our binary.

    Now we need to make sure our fonts make it to our CSS. What we typically do is we create a file called: _fonts.scss. In there, you can add your font definitions, like the following:

    @font-face {
      font-family: "My Custom Font";
      font-style: normal;
      font-weight: 300;
      src: local("My Custom Font"), 
           url("/assets/fonts/myFont.woff") format("woff");
    }
    

    This will ensure that the app pulls your fonts from the assets folder, and finally will make your font available to be used in your app.

    Wrapping up

    With this brief post I shared a bit on how asset files are handled by Buffalo. I also showed a bit of the compilation details of the buffalo binary, and how to add custom fonts into your buffalo app.

    If you like this, don’t hesitate to share it. I would love to read/hear your opinions.

    Continue Reading
  • Daniel Oviedo on September 13, 2019

    Testing the Visuals of IE11 & Microsoft Edge on a MAC OS using VirtualBox

    As developers one of our duties is to ensure consistency in how content is displayed in a variety of browsers. If your web development project involves testing the visuals on IE11 or Microsoft Edge and don’t know how because you are using MacOS, then this post is for you! Note that you do not need a serial number or purchase anything in order to install Windows 10.

    I‘ll expose a fairly simple and popular way to operate Bill Gates’ giant having Steve Jobs as host using Oracle’s VirtualBox. The steps are as follows:

    1. Install Oracle’s VirtualBox.
    2. Install Microsoft 10 using a .iso file in VirtualBox.
    3. Testing your project with IE11 and Microsoft Edge.

    Let’s dive into the details of each step:

    1. Install Oracle’s VirtualBox

    Go to https://www.virtualbox.org/wiki/Downloads and under “VirtualBox 6.0.12 platform packages” label (as of today the current version is 6.0.12), click on “OS X hosts”

    image

    After the download finishes click the installer and follow the steps. You’ll be likely asked to grant accessibility features for VirtualBox in System Preferences. This may be relevant to avoid future problems when running the virtual machine, so make sure to allow it.

    2. Now we need to download Windows 10 .iso file and install it in VirtualBox. There are two main sub-steps:

    2.1 - Downloading Windows 10:

    Go to https://www.microsoft.com/en-us/software-download/windows10ISO. Under “Select edition” tab, select Windows 10 (Latest is 10 May 2019 as of today). Click on Confirm. Now select the language and click again on Confirm.

    image

    Download 32-bit or 64-bit version. I’m sticking with 64-bit version, but feel free to choose what best fits your setup. If your internet is not so speedy you might sit a while and wait until the download finishes.

    image

    2.2 - Installing Windows 10 in VirtualBox:

    Open VirtualBox and click on “New”, then enter a name for the virtual machine. I use “Windows 10 - 64bit”. Make sure “Type” is set to “Microsoft Windows” and in “Version” select “Windows 10 (64 bit)”. Click on continue.

    image

    In this step you need to allocate enough RAM. I assigned it 2GB since I have 8GB RAM in my iMac and I don’t want to run into performance issues in my host machine. Have in mind that x86 (32-bit) version requires a minimum of 1GB RAM and x64 version requires 2GB RAM at least. Click on “Continue”.

    image

    You need to create a Virtual Hard Disk. The default selected option is fine (Create a virtual hard disk now), click on “Create”. Select “VDI (VirtualBox Disk Image)” and choose “Fixed Size HDD”. Microsoft requires 16GB at least for 32-bit version and 20GB for 64-bit version. I’ll set mine to 50GB.

    image

    Make sure to allocate enough video resources to your guest OS. You can check those options in “Settings” then “Display” tab. If you’re not sure, leave default and adjust later.

    Go to “Settings”, click on the “Storage” tab, click on the blue “Empty” disk and click the blue disk to the right of “SATA Port 1”, click on “Choose Virtual Optical Disk Drive” and look for your Windows 10 .iso file.

    image

    Start your Windows 10 virtual machine and follow the installation instructions. As I mentioned earlier, don’t worry about the serial number, just select you don’t have one and it will anyway let you install.

    image

    After finishing installation you should have your Windows 10 up and running.

    3. Testing your project with IE11 and Microsoft Edge

    The default settings should be fine to let communication happen between host OS and guest OS. To know which IP address to point inside Windows 10, open the Command Prompt or the Powershell and run the following command:

    ipconfig

    The Default Gateway is the IP address we should use to connect with MacOS host, in my case is 10.0.2.2.

    image

    If you’re already serving a project in MacOS go ahead and test in IE11 or Microsoft Edge. For example I just created and deployed locally in my host machine a Vue.js app using Vue’s CLI and it listens on port 8080:

    image

    That’s it folks! Now you’re ready to see the looks of your project with IE11 and Microsoft Edge within MacOS. Also, feel free to experiment with Windows 10 as you need.

    Continue Reading
  • Larry Morales on September 9, 2019

    How Emergent Design Solved N+1 Problem In Buffalo Pop

    Disclaimer. Those who are not familiarized with N+1 problem, you can check “What is the N+1 selects problem in ORM(Object-Relational Mapping) with details explaining the concept.

    Since associations were introduced in Pop, the N+1 problem became part of it: many queries hit the database in order to load whole model’s associations. Good news is N+1 problem is not a disease without remedy. In this post I will give you some steps I took to solve it by incorporating emergent design.

    Step 1: Start Coding By Example

    Coding by example helps you to define what’s your input and what’s your output. Code By Example means you define a scenario where  your solution is tested and what is the expected result. The method I used to apply this technique was Test Driven Development (TDD).

    I started to code by example for the most simple scenario I could think of. To me, the most simple scenario was to solve N+1 problem for the has_many type association.

    =========== Scenario 1 =============================
    
     Given I have 3 Users with one Book each one related
     Then I would expect the query performed to be:
    
     select books.* from books where user_id in ($1, $2, $3)
    

    This, translated into code, would be:

      // pop_test.go
      type User struct {
         ...
         Books []Book `has_many: “books”` 
      }
    
      // pop_test.go
      type Book struct {
         ...
         UserID int `db:”user_id”` 
      }
    
    // preload_associations_test.go
    func TestHasManyNPlusOneSolution(t *testing.T) {
       ...
    
      for i:= 1; i <= 3; i++ {
          user := User{}
          tx.Create(&user)
          
          tx.Create(&Book{
              UserID: user.ID,
          })
       }
    
      Debug = true
    
      users := []User{}
      preload(tx, &users)
    
      a.Equal(3, len(users))
      a.Equal(1, len(users[0].Books)
      a.Equal(users[0].ID, users[0].Books[0].UserID)
    }
    
    // preload_association.go
    func preload(tx *Connection, model []User) error {
    	return nil
    }
    

    Step 2: Be Explicit With Your Input And Output.

    As soon as I wrote down the scenario, I noticed there are three things that I needed to do in order to produce the desire output:

    • First thing is to iterate over every user and store its ID value in a slice.

    • Second thing is that user_id column in the expected query result. I need to pull it out from db tag in Book model.

    • Third thing is to link all books with their respective users once the query is successful.

    Because I’m in a premature start point, and I don’t want to go into the code details about how to read that field tag, In order to make that test to pass as quickly as possible, I hard-coded the solution and be explicit to have that test with a green face.

    func preload(tx *Connection, model []User) error {
        // 1) fill in ids.
        ids := []interface{}
        for _, u := range model {
            ids = append(ids, u.ID)
        }
        
        // 2) load associations.
        books := []books{}
        tx.Where(“user_id in (?)”, ids).All(&books)
        
        // 3) fill in model with associations.
        for i := range model {
            for _, book := range books {
                if book.UserID == model[i].ID {
                    model[i].Books = append(model[i].Books, book)
                }
            }
        }
    }
    
    

    Step 3: Go From Specific To Generic.

    Once I have green light and test is passing, I noticed the solution was composed into a three steps process:

    1. fill in ids.
    2. load associations.
    3. fill in model with associations.

    At this stage I need to be less specialized and be more generic with the solution. The reason is this moment preload function only knows how to preload users and books, but models can be from different types.

    In order to achieve generalization, I take one step at the time and apply some refactorings techniques until I’ve satisfied the desired generic level.

    I started to refactor step one (fill in ids). In this step, the generic level I want to achieve is to get a list of all ids value from model, no matter what type that model is. This pushed me to incorporate some reflections code and go a little deep in details in order to get the expected result. For every tiny change I applied to my code, I ran my test making sure is still getting green.

    Once I got the level of abstraction I want for my step one, I move on to step two (load associations) and do same thing. I stablish first wich is the generic level I want to go, and then apply all code changes and refactorings necessary to achieve the correct result. Once I’m done with step two I then move on to step three, always trying to achieve generalization. Here is the result of applying this process to the has_many preload function.

    Step 4: Repeat, Repeat and Repeat.

    Once I feel I’m done with has_many type association, I start to cycle again following same process for has_one type association. I repeat same three steps: Code By Example, Be Explicit and Be Generic (from now on CBB) until I got all four type associations covered. https://github.com/gobuffalo/pop/blob/nplus1/preload_associations.go#L158

    Wrapping up

    As software developers we tend to find code solutions based on our experience in one project and try to reuse them in other projects where we think they’ll match up. Sometimes, there are cases where uncertainty is a variable, and applying CBB process helped me to overcome that. I’ve testified the good impact this process has. The way that solution design emerges, without a deliberated thoughtful specification in mind. It feels like an organic living growing from its seed. Give it a try and let me know how it works for you.

    Thank you for reading this post. I hope you have enjoyed how emergent design helped me  to find solutions to N+1 problem in Buffalo/Go, and hope you apply it into your projects.

    Continue Reading