Skip to main content

Non-Test vs Test Driven Developer in Golang

There's been a lot of debates on whether TDD is dead or not! I strongly believe that TDD is very essential in any serious Software Development endeavor, especially for any team which is currently embracing  MICRO-services architecture or might seek to transition to Micro-services later.
TDD somewhat will drive you to work out better and better system design rather than just focus on increasing Code Coverage as a vanity metric. The more you aim to improve Testability and TDD compliance in every single piece of your software, the easier you can extend or modify any functionalities in your system.
I'm gonna share some pieces of codes to help illustrate my points regarding how different they are in practiceLet's dive into those differences
//Non-Test
package client

import (
   "bitbucket.org/sakariai/sakari/proto"
   "go.elastic.co/apm/module/apmgrpc"
   "google.golang.org/grpc"
)

type Volante struct {
   proto.VolanteClient
   conn *grpc.ClientConn
}

func NewInternalVolanteClient(address string) (*Volante, error) {
   client, disconnection, err := withInfo(address)
   if err != nil {
      return nil, err
   }
   vl := &Volante{VolanteClient: client, conn: disconnection}

   return vl, nil
}

func withInfo(address string) (proto.VolanteClient, *grpc.ClientConn, error) {
   conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithUnaryInterceptor(apmgrpc.NewUnaryClientInterceptor()))
   if err != nil {
      return nil, nil, err
   }
   client := proto.NewVolanteClient(conn)

   return client, conn, nil
}

func (v Volante) Close() error {
   return v.conn.Close()
}
And...
//Test Driven
package client

import (
   "io"

   "bitbucket.org/sakariai/sakari/proto"
   "go.elastic.co/apm/module/apmgrpc"
   "google.golang.org/grpc"
)

type Connector func(string) (proto.VolanteClient, io.Closer, error)

//go:generate mockgen -destination mock_volante.go -package=client bitbucket.org/sakariai/sakari/proto VolanteClient
type Volante struct {
   proto.VolanteClient
   conn      io.Closer
   address   string
}

var DefaultConnector = withInfo


func NewInternalVolanteClient(address string, cn Connector) (*Volante, error) {
   client, disconnection, err := cn(address)
   if err != nil {
      return nil, err
   }
   vl := &Volante{VolanteClient: client, conn: disconnection}

   return vl, nil
}

//For non-test adoption
func DefaultVolante(address string) (*Volante, error) {
   return NewInternalVolanteClient(address, DefaultConnector)
}

//Simlar above
func withInfo(address string) (proto.VolanteClient, io.Closer, error) {
   ...
}

func (v Volante) Close() error {
   return v.conn.Close()
}
* The first approach is not easy to be utilized for other companies if they need to write (unit) tests for their project. Because *grpc.ClientConn is not friendly in Close() function
* By having connector which returns 2 interfaces(io.Closer interface replaces grpc.Conn Struct), which are natural for mocking purposes in an outer package. With this implementation, NewInternalVolanteClient is easy to accommodate any future need for further development regarding test.
func testConnector(t *testing.Test){
  mockConnector := func(address string) {
     return mockProtoVolanteClient, mockIo.Closer, nil
  }
  volante := NewInternalVolanteClient("volante", mockConnector)
  ...
}
I'm pretty sure, Volante variable is pretty comfortable to function in your test environment.
Let's rock to be TEST DRIVEN DEVELOPERLet's rock to be TEST DRIVE DEVELOPER

Comments

  1. I'm really impressed with your writing skills, as smart as the structure of your weblog.

    GoLand Full Crack

    Waves v12 Complete Crack

    ReplyDelete
  2. Developed by NetEnt amounts to more than 200 and there are lots of|there are numerous} of them which have been among the many most popular for on-line on line casino players since their release. The PowerUP Roulette live on line casino sport 바카라 사이트 show is a highly anticipated take on the classic Roulette sport, with up to as} 5 PowerUP bonus rounds providing extra chances to win. The greatest video poker video games with your favourite pay tables, starting at 5 cent denomination.

    ReplyDelete

Post a Comment

Popular posts from this blog

Pivot Query in Postgresql is much better than Pivot_Table in Pandas

Pivot Query in Postgresql select * from crosstab ( $$ SELECT anonymous_id, message_id , timestamp, key, value FROM pixels WHERE tenant_id = 2 AND pixels.timestamp >= '2019-10-19 10:41:03.254968' AND pixels.timestamp < '2019-10-20 10:41:03.254968' AND message_id = ANY(SELECT message_id FROM pixels WHERE tenant_id = 2 AND pixels.timestamp >= '2019-10-19 10:41:03.254968' AND pixels.timestamp < '2019-10-20 10:41:03.254968' AND key = 'event' AND value = 'init_banuba_success' ) AND (key = ANY(array['context.timezone','context.device.model','