Quantcast

Testing Micro Services

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Testing Micro Services

Mika'il
Hello,

I am a software engineer and have been coding for the last 10 years in a variety of imperative
languages (C, C++, Java). Recently, I have joined a new company where I write Scala 
and am working on a project where we are building microservices using Scala Play.

For the past year in my spare time I have been learning Haskell, FP, and bits of Category 
Theory and I love it. Haskell has really made me interested in programming once again. Also 
the fact that I can relate mathematical theory to my code makes it even more appealing. So 
whenever I work on a project now, I always think how I could write the equivalent program
in Haskell. My long terms goal is to gain sufficient experience in Haskell to actually be able
to recommend it in an industrial setting with confidence; I would really like to be able to do that.

On my current project, the team has designed the microservices in a non-functional way. No one
on the team is familiar with FP. They are former Java programmers and are really just porting their
OOP mindset to every problem. The resulting code whilst still written in Scala is really just Java in 
disguise - something which has been coined as Jala (Java + Scala).

When I initially looked at their design which involves heavy use of inheritance and some design
patterns, I began to think what the equivalent FP solution would look like. After some thought, I 
eventually wrote a single typeclass which captured the essence of the problem domain. I 
demonstrated this to the team and they were simply blown away that a single typeclass was all 
that was needed to model the problem. It also solved other problems which they were experiencing
with their current design.

However, I got stuck on the testing aspects of the microservice. With the original design the team had
followed Martin Fowler's recommendations for testing microservices 
(http://martinfowler.com/articles/microservice-testing/). This resulted in a lot of testing code to test all the 
HTTP layers from unit tests, integration tests, component tests and finally end-to-end tests). The tests also 
relied heavily on the Mockito framework to mock all the external services which interacted with the microservice.

I simply could not think of how I would or if I needed to do all this testing with my equivalent FP solution.
All I have with my solution is a few functions which I could easily write unit tests for if need be. Do I really
need to write mocks for the external services? I could not find any thing on the internet which deals with
this area. In fact, I think this is an area where FP literature is lacking. We have a lot of literature on FP
theory, FP languages and design techniques, but very little on testing.

I did come across Michael Snoyman's article here (http://www.yesodweb.com/blog/2012/01/aosa-chapter) where
he states:

In most dynamically-typed languages, and their web frameworks, the recommended approach to solving this issue is writing unit tests. If you have full test coverage, then running your tests will immediately reveal what code needs to be updated. This is all well and good, but it is a weaker solution than true types:
  • It is all predicated on having full test coverage. This takes extra time, and worse, is boilerplate code that the compiler should be able to do for you.
  • You might be a perfect developer who never forgets to write a test, but can you say the same for every person who will touch your codebase?
  • Even 100% test coverage doesn't guarantee that you really have tested every case. All it's done is proven you've tested every line of code.
Is Michael stating here that there is no need for tests because all the information about the problem is encoded in the types?

Regards,
Mika'il

--
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Testing Micro Services

Alexander V Vershilov
Hello, Mika'il.

First I want to mention that haskell, is not a language that differ
much from other
widely used language from the testing perspective, it's not a language where you
don't need to write a test, or even run your program at all (because
it typechecks,
and that is everything you need).

The type system is not the silver button, it doesn't give any
additional correctness
guarantees, over invariants that it describes. Let me give you a very
simple example:
boolean blindness. Assume we have microservice based on servant framework,
that service have endpoint with type:

"more-than-255" :> Capture "number-to-test" Int :> Get Bool.

Type here guarantees that it will accept an integer and return a
boolean with a result,
so you should not write huge number of boring tests to assert that.
However programmer could write:
```
implementation :: Int -> EitherT ServantError IO Bool
implementation number = return $ number < 255
```
and type system will be happy with that. But  code is incorrect.
So, even in Haskell you need to have unit-tests (for testing hard
units of code, or units
where some bug appears, or all units if you live 100% test coverage),
integration or system
tests in order to check that entire system working correctly and you
have not introduced
any problem that do not breaks internal invariants, but breaks
external ones, you
still may need to have performance tests if that is a part of the
guarantees that work
you deliver should pass, or other sophisticated tests that you may need.
Of cause you could try to find a language, or tricks that could encode
more interesting
invariants in a type system, and have more "tests" that will be "run"
by compiler for free,
but finding an ideal compromise with expressiveness of the invariants
expressed in a type
system, and easiness of writing and refactoring code so those
invariants could be
checked by the compiler is an open problem.

Another thing, is that if you have some microservice written in
servant like framework
you will have different layers of API description, implementation and
glue that ties them
together (another frameworks may have a similar guarantee). This means that your
implementation is an ordinary haskell function, so you could forget
that it's a part of
some web service and test your function like other haskell code. This
way you archive
additional modularity, and you when you are writing your tests, then
you are saying
"my function works properly if underlying framework works properly",
this makes tests
easier to write. And if for some reason you'll have to move to the
other architecture,
like using other message passing mechanism instead of running in
web-services, or
using for expample, Cloud Haskell, or have those interfaces at the same time.
You will not need to change your tests and functions implementation
and could refactor
code easily.

As for tests, there are 2 widely accepted approaches for writing tests, they are
1. QuickCheck -- that tests properties using random input
   https://hackage.haskell.org/package/QuickCheck-2.8.1
2. SmallCheck -- tests properties using all possible inputs up to the
certain depth
   https://hackage.haskell.org/package/smallcheck
3. HUnit -- unit testing, that checks fixed scenarios (inspired by JUnit)
   https://hackage.haskell.org/package/HUnit
And testing frameworks that ties different test types and give a way
to wrap them
into controllable test suites:
1. Tasty: https://hackage.haskell.org/package/tasty
2. Test-framework: https://hackage.haskell.org/package/test-framework
3. Hspec: https://hackage.haskell.org/package/hspec
4. sorry if I didn't mention others works.
They are all solving similar tasks and are different in details, so
I'll not give my personal
opinion about what to use.


On 1 January 2016 at 21:30, Mika'il <[hidden email]> wrote:

> Hello,
>
> I am a software engineer and have been coding for the last 10 years in a
> variety of imperative
> languages (C, C++, Java). Recently, I have joined a new company where I
> write Scala
> and am working on a project where we are building microservices using Scala
> Play.
>
> For the past year in my spare time I have been learning Haskell, FP, and
> bits of Category
> Theory and I love it. Haskell has really made me interested in programming
> once again. Also
> the fact that I can relate mathematical theory to my code makes it even more
> appealing. So
> whenever I work on a project now, I always think how I could write the
> equivalent program
> in Haskell. My long terms goal is to gain sufficient experience in Haskell
> to actually be able
> to recommend it in an industrial setting with confidence; I would really
> like to be able to do that.
>
> On my current project, the team has designed the microservices in a
> non-functional way. No one
> on the team is familiar with FP. They are former Java programmers and are
> really just porting their
> OOP mindset to every problem. The resulting code whilst still written in
> Scala is really just Java in
> disguise - something which has been coined as Jala (Java + Scala).
>
> When I initially looked at their design which involves heavy use of
> inheritance and some design
> patterns, I began to think what the equivalent FP solution would look like.
> After some thought, I
> eventually wrote a single typeclass which captured the essence of the
> problem domain. I
> demonstrated this to the team and they were simply blown away that a single
> typeclass was all
> that was needed to model the problem. It also solved other problems which
> they were experiencing
> with their current design.
>
> However, I got stuck on the testing aspects of the microservice. With the
> original design the team had
> followed Martin Fowler's recommendations for testing microservices
> (http://martinfowler.com/articles/microservice-testing/). This resulted in a
> lot of testing code to test all the
> HTTP layers from unit tests, integration tests, component tests and finally
> end-to-end tests). The tests also
> relied heavily on the Mockito framework to mock all the external services
> which interacted with the microservice.
>
> I simply could not think of how I would or if I needed to do all this
> testing with my equivalent FP solution.
> All I have with my solution is a few functions which I could easily write
> unit tests for if need be. Do I really
> need to write mocks for the external services? I could not find any thing on
> the internet which deals with
> this area. In fact, I think this is an area where FP literature is lacking.
> We have a lot of literature on FP
> theory, FP languages and design techniques, but very little on testing.
>
> I did come across Michael Snoyman's article here
> (http://www.yesodweb.com/blog/2012/01/aosa-chapter) where
> he states:
>
>> In most dynamically-typed languages, and their web frameworks, the
>> recommended approach to solving this issue is writing unit tests. If you
>> have full test coverage, then running your tests will immediately reveal
>> what code needs to be updated. This is all well and good, but it is a weaker
>> solution than true types:
>>
>> It is all predicated on having full test coverage. This takes extra time,
>> and worse, is boilerplate code that the compiler should be able to do for
>> you.
>>
>> You might be a perfect developer who never forgets to write a test, but
>> can you say the same for every person who will touch your codebase?
>>
>> Even 100% test coverage doesn't guarantee that you really have tested
>> every case. All it's done is proven you've tested every line of code.
>
> Is Michael stating here that there is no need for tests because all the
> information about the problem is encoded in the types?
>
> Regards,
> Mika'il
>
> --
>
> "Commercial Haskell" group.
>
> email to [hidden email].
>
>
> https://groups.google.com/d/msgid/commercialhaskell/4aaa16b1-8372-4c21-ade8-6b2b5114aa05%40googlegroups.com.
>



--
Alexander

--





Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Testing Micro Services

Arnaud Bailly | Capital Match
In reply to this post by Mika'il
Hi Mika'il,



On Fri, Jan 1, 2016 at 7:30 PM, Mika'il <[hidden email]> wrote:
Hello,
 
When I initially looked at their design which involves heavy use of inheritance and some design
patterns, I began to think what the equivalent FP solution would look like. After some thought, I 
eventually wrote a single typeclass which captured the essence of the problem domain. I 
demonstrated this to the team and they were simply blown away that a single typeclass was all 
that was needed to model the problem. It also solved other problems which they were experiencing
with their current design.


Capturing the essence of a domain language can be done in any language, any framework, any environment. This approach has been coined as DDD and was originally mostly applied in an OO setting. There is nothing special to Haskell here, except the fact that you used a type-class which is something that is close to an interface in Java but not quite identical. you could have modelled your domain using a bunch of simple class/objects.

However, I got stuck on the testing aspects of the microservice. With the original design the team had
followed Martin Fowler's recommendations for testing microservices 
(http://martinfowler.com/articles/microservice-testing/). This resulted in a lot of testing code to test all the 
HTTP layers from unit tests, integration tests, component tests and finally end-to-end tests). The tests also 
relied heavily on the Mockito framework to mock all the external services which interacted with the microservice.


That's a sure smell: Mocks are useful in any language to abstract away requirements from your components, not constraints. This means the need for mock is driven by usage (interfaces, or typeclasses) and not by implementation (e.g. concrete behaviour of a service). In microservices one could use the consumer-driven contact approach to expose clients' requirements as tests (or specifications) to be fulfilled by providers, e.g. other services.

I simply could not think of how I would or if I needed to do all this testing with my equivalent FP solution.
All I have with my solution is a few functions which I could easily write unit tests for if need be. Do I really
need to write mocks for the external services? I could not find any thing on the internet which deals with
this area. In fact, I think this is an area where FP literature is lacking. We have a lot of literature on FP
theory, FP languages and design techniques, but very little on testing.


Indeed. Most Haskell books are lacking in this respect and I long for a book which would be called Growing Functional Programming Software guided by Tests.

 
I did come across Michael Snoyman's article here (http://www.yesodweb.com/blog/2012/01/aosa-chapter) where
he states:

In most dynamically-typed languages, and their web frameworks, the recommended approach to solving this issue is writing unit tests. If you have full test coverage, then running your tests will immediately reveal what code needs to be updated. This is all well and good, but it is a weaker solution than true types:
  • It is all predicated on having full test coverage. This takes extra time, and worse, is boilerplate code that the compiler should be able to do for you.
  • You might be a perfect developer who never forgets to write a test, but can you say the same for every person who will touch your codebase?
  • Even 100% test coverage doesn't guarantee that you really have tested every case. All it's done is proven you've tested every line of code.
Is Michael stating here that there is no need for tests because all the information about the problem is encoded in the types?


I would not speak for Michael. My personal take is that types are great but they can only state static invariants, by construction. They only tell part of the story and are extremely useful, but so are tests. I like to use tests as a way to drive my design, at all level. This means writing the test first and use it to explore and perfect design of the software, including the tests. Then more tests might help refine the behaviour, and possibly the types, of the software.

Regarding your specific problem, an interesting approach you might want to explore is using Monadic QuickCheck.

Best regards,
--
Arnaud Bailly
CTO | 
Capital Match
CapitalMatch
39A ​North Canal Road | Singapore ​059295
<a href="tel:%2B33%20617%20121%20978" value="+6594299471" target="_blank">+33 617 121 978 | [hidden email] | www.capital-match.com

Capital Match Platform Pte. Ltd., registered in Singapore (Co. Reg. No. 201501788H), is a subsidiary of Capital Match Holdings Pte. Ltd. (Co. Reg. No. 201418682W) (collectively "Capital Match").

This e-mail message and any enclosures are intended only for the person(s) to whom it is addressed and may contain information which is confidential and/or legally protected. Any use, distribution, modification, copying or disclosure by any person(s) other than the named addressee is strictly prohibited. Capital Match disclaims all responsibility from and accept no liability whatsoever for the consequences of any unauthorized person acting, or refraining from acting, on any information contained in this message. If you have received this email in error, please inform us immediately and delete it and all copies from your system.

E-mail transmission cannot be guaranteed to be secure or error-free as information could be intercepted, corrupted, lost, destroyed, arrive later or incomplete, or contain viruses. The sender therefore does not accept liability for any errors or omissions in the contents of this message which arise as a result of e-mail transmission. If verification is required, please request a hard-copy version from the sender. Capital Match makes no representation or warranty as to the absence of viruses in this e-mail or any attachments.

--
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Testing Micro Services

Mika'il
In reply to this post by Alexander V Vershilov
Thanks Alexander.

That's confirmed my thoughts as well that I do still need to write tests. I just
needed that confirmation from experts on this forum. I will look into the links 
you have provided.

Regards,
Mika'il.

On Friday, 1 January 2016 20:08:16 UTC, Alexander Vershilov wrote:
Hello, Mika'il.

First I want to mention that haskell, is not a language that differ
much from other
widely used language from the testing perspective, it's not a language where you
don't need to write a test, or even run your program at all (because
it typechecks,
and that is everything you need).

The type system is not the silver button, it doesn't give any
additional correctness
guarantees, over invariants that it describes. Let me give you a very
simple example:
boolean blindness. Assume we have microservice based on servant framework,
that service have endpoint with type:

"more-than-255" :> Capture "number-to-test" Int :> Get Bool.

Type here guarantees that it will accept an integer and return a
boolean with a result,
so you should not write huge number of boring tests to assert that.
However programmer could write:
```
implementation :: Int -> EitherT ServantError IO Bool
implementation number = return $ number < 255
```
and type system will be happy with that. But  code is incorrect.
So, even in Haskell you need to have unit-tests (for testing hard
units of code, or units
where some bug appears, or all units if you live 100% test coverage),
integration or system
tests in order to check that entire system working correctly and you
have not introduced
any problem that do not breaks internal invariants, but breaks
external ones, you
still may need to have performance tests if that is a part of the
guarantees that work
you deliver should pass, or other sophisticated tests that you may need.
Of cause you could try to find a language, or tricks that could encode
more interesting
invariants in a type system, and have more "tests" that will be "run"
by compiler for free,
but finding an ideal compromise with expressiveness of the invariants
expressed in a type
system, and easiness of writing and refactoring code so those
invariants could be
checked by the compiler is an open problem.

Another thing, is that if you have some microservice written in
servant like framework
you will have different layers of API description, implementation and
glue that ties them
together (another frameworks may have a similar guarantee). This means that your
implementation is an ordinary haskell function, so you could forget
that it's a part of
some web service and test your function like other haskell code. This
way you archive
additional modularity, and you when you are writing your tests, then
you are saying
"my function works properly if underlying framework works properly",
this makes tests
easier to write. And if for some reason you'll have to move to the
other architecture,
like using other message passing mechanism instead of running in
web-services, or
using for expample, Cloud Haskell, or have those interfaces at the same time.
You will not need to change your tests and functions implementation
and could refactor
code easily.

As for tests, there are 2 widely accepted approaches for writing tests, they are
1. QuickCheck -- that tests properties using random input
   <a href="https://hackage.haskell.org/package/QuickCheck-2.8.1" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2FQuickCheck-2.8.1\46sa\75D\46sntz\0751\46usg\75AFQjCNEIIR4TaTr1BCEMvNHxv1k0qsRFEg&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2FQuickCheck-2.8.1\46sa\75D\46sntz\0751\46usg\75AFQjCNEIIR4TaTr1BCEMvNHxv1k0qsRFEg&#39;;return true;">https://hackage.haskell.org/package/QuickCheck-2.8.1
2. SmallCheck -- tests properties using all possible inputs up to the
certain depth
   <a href="https://hackage.haskell.org/package/smallcheck" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2Fsmallcheck\46sa\75D\46sntz\0751\46usg\75AFQjCNFt44LXjhsZPx4CHGHPscmYGprRow&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2Fsmallcheck\46sa\75D\46sntz\0751\46usg\75AFQjCNFt44LXjhsZPx4CHGHPscmYGprRow&#39;;return true;">https://hackage.haskell.org/package/smallcheck
3. HUnit -- unit testing, that checks fixed scenarios (inspired by JUnit)
   <a href="https://hackage.haskell.org/package/HUnit" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2FHUnit\46sa\75D\46sntz\0751\46usg\75AFQjCNEQ2fslT900mUAWzjlhenFESKQLTQ&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2FHUnit\46sa\75D\46sntz\0751\46usg\75AFQjCNEQ2fslT900mUAWzjlhenFESKQLTQ&#39;;return true;">https://hackage.haskell.org/package/HUnit
And testing frameworks that ties different test types and give a way
to wrap them
into controllable test suites:
1. Tasty: <a href="https://hackage.haskell.org/package/tasty" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2Ftasty\46sa\75D\46sntz\0751\46usg\75AFQjCNEKBEC0dUNVdXcCfO1KNMBuYvpv8w&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2Ftasty\46sa\75D\46sntz\0751\46usg\75AFQjCNEKBEC0dUNVdXcCfO1KNMBuYvpv8w&#39;;return true;">https://hackage.haskell.org/package/tasty
2. Test-framework: <a href="https://hackage.haskell.org/package/test-framework" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2Ftest-framework\46sa\75D\46sntz\0751\46usg\75AFQjCNGAdv7eVzmczZCkVRtls-5wTxQJVQ&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2Ftest-framework\46sa\75D\46sntz\0751\46usg\75AFQjCNGAdv7eVzmczZCkVRtls-5wTxQJVQ&#39;;return true;">https://hackage.haskell.org/package/test-framework
3. Hspec: <a href="https://hackage.haskell.org/package/hspec" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2Fhspec\46sa\75D\46sntz\0751\46usg\75AFQjCNG-lWcT1SsPZOu2N4pZ3ve1Ep_Cnw&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fhackage.haskell.org%2Fpackage%2Fhspec\46sa\75D\46sntz\0751\46usg\75AFQjCNG-lWcT1SsPZOu2N4pZ3ve1Ep_Cnw&#39;;return true;">https://hackage.haskell.org/package/hspec
4. sorry if I didn't mention others works.
They are all solving similar tasks and are different in details, so
I'll not give my personal
opinion about what to use.


On 1 January 2016 at 21:30, Mika'il <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="lFE_cuTgAQAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">co.kl...@...> wrote:

> Hello,
>
> I am a software engineer and have been coding for the last 10 years in a
> variety of imperative
> languages (C, C++, Java). Recently, I have joined a new company where I
> write Scala
> and am working on a project where we are building microservices using Scala
> Play.
>
> For the past year in my spare time I have been learning Haskell, FP, and
> bits of Category
> Theory and I love it. Haskell has really made me interested in programming
> once again. Also
> the fact that I can relate mathematical theory to my code makes it even more
> appealing. So
> whenever I work on a project now, I always think how I could write the
> equivalent program
> in Haskell. My long terms goal is to gain sufficient experience in Haskell
> to actually be able
> to recommend it in an industrial setting with confidence; I would really
> like to be able to do that.
>
> On my current project, the team has designed the microservices in a
> non-functional way. No one
> on the team is familiar with FP. They are former Java programmers and are
> really just porting their
> OOP mindset to every problem. The resulting code whilst still written in
> Scala is really just Java in
> disguise - something which has been coined as Jala (Java + Scala).
>
> When I initially looked at their design which involves heavy use of
> inheritance and some design
> patterns, I began to think what the equivalent FP solution would look like.
> After some thought, I
> eventually wrote a single typeclass which captured the essence of the
> problem domain. I
> demonstrated this to the team and they were simply blown away that a single
> typeclass was all
> that was needed to model the problem. It also solved other problems which
> they were experiencing
> with their current design.
>
> However, I got stuck on the testing aspects of the microservice. With the
> original design the team had
> followed Martin Fowler's recommendations for testing microservices
> (<a href="http://martinfowler.com/articles/microservice-testing/" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fmartinfowler.com%2Farticles%2Fmicroservice-testing%2F\46sa\75D\46sntz\0751\46usg\75AFQjCNGBQEurXP3AGE43tl-1SgF7yn2nsw&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fmartinfowler.com%2Farticles%2Fmicroservice-testing%2F\46sa\75D\46sntz\0751\46usg\75AFQjCNGBQEurXP3AGE43tl-1SgF7yn2nsw&#39;;return true;">http://martinfowler.com/articles/microservice-testing/). This resulted in a
> lot of testing code to test all the
> HTTP layers from unit tests, integration tests, component tests and finally
> end-to-end tests). The tests also
> relied heavily on the Mockito framework to mock all the external services
> which interacted with the microservice.
>
> I simply could not think of how I would or if I needed to do all this
> testing with my equivalent FP solution.
> All I have with my solution is a few functions which I could easily write
> unit tests for if need be. Do I really
> need to write mocks for the external services? I could not find any thing on
> the internet which deals with
> this area. In fact, I think this is an area where FP literature is lacking.
> We have a lot of literature on FP
> theory, FP languages and design techniques, but very little on testing.
>
> I did come across Michael Snoyman's article here
> (<a href="http://www.yesodweb.com/blog/2012/01/aosa-chapter" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.yesodweb.com%2Fblog%2F2012%2F01%2Faosa-chapter\46sa\75D\46sntz\0751\46usg\75AFQjCNHdk8rUsIbJmwM96lZvS_UIbRE8wA&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.yesodweb.com%2Fblog%2F2012%2F01%2Faosa-chapter\46sa\75D\46sntz\0751\46usg\75AFQjCNHdk8rUsIbJmwM96lZvS_UIbRE8wA&#39;;return true;">http://www.yesodweb.com/blog/2012/01/aosa-chapter) where
> he states:
>
>> In most dynamically-typed languages, and their web frameworks, the
>> recommended approach to solving this issue is writing unit tests. If you
>> have full test coverage, then running your tests will immediately reveal
>> what code needs to be updated. This is all well and good, but it is a weaker
>> solution than true types:
>>
>> It is all predicated on having full test coverage. This takes extra time,
>> and worse, is boilerplate code that the compiler should be able to do for
>> you.
>>
>> You might be a perfect developer who never forgets to write a test, but
>> can you say the same for every person who will touch your codebase?
>>
>> Even 100% test coverage doesn't guarantee that you really have tested
>> every case. All it's done is proven you've tested every line of code.
>
> Is Michael stating here that there is no need for tests because all the
> information about the problem is encoded in the types?
>
> Regards,
> Mika'il
>
> --
>
> "Commercial Haskell" group.
>
> email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="lFE_cuTgAQAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">commercialhask...@googlegroups.com.
>
>
> <a href="https://groups.google.com/d/msgid/commercialhaskell/4aaa16b1-8372-4c21-ade8-6b2b5114aa05%40googlegroups.com" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/msgid/commercialhaskell/4aaa16b1-8372-4c21-ade8-6b2b5114aa05%40googlegroups.com&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/msgid/commercialhaskell/4aaa16b1-8372-4c21-ade8-6b2b5114aa05%40googlegroups.com&#39;;return true;">https://groups.google.com/d/msgid/commercialhaskell/4aaa16b1-8372-4c21-ade8-6b2b5114aa05%40googlegroups.com.
>



--
Alexander

--
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Testing Micro Services

Mika'il
In reply to this post by Arnaud Bailly | Capital Match
Thanks Arnaud for your insight.

I did a search for Monadic QuickCheck and few things have popped up which I will look into; I 
guess I just did not know what to search for:

https://blog.pusher.com/unit-testing-io-in-haskell/
http://engineering.imvu.com/2015/06/20/testable-io-in-haskell-2/

Thanks for the tip!

Regards,
Mika'il.

On Friday, 1 January 2016 21:06:00 UTC, Arnaud Bailly wrote:
Hi Mika'il,



On Fri, Jan 1, 2016 at 7:30 PM, Mika'il <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="EQjsxwrkAQAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">co.kl...@...> wrote:
Hello,
 
When I initially looked at their design which involves heavy use of inheritance and some design
patterns, I began to think what the equivalent FP solution would look like. After some thought, I 
eventually wrote a single typeclass which captured the essence of the problem domain. I 
demonstrated this to the team and they were simply blown away that a single typeclass was all 
that was needed to model the problem. It also solved other problems which they were experiencing
with their current design.


Capturing the essence of a domain language can be done in any language, any framework, any environment. This approach has been coined as DDD and was originally mostly applied in an OO setting. There is nothing special to Haskell here, except the fact that you used a type-class which is something that is close to an interface in Java but not quite identical. you could have modelled your domain using a bunch of simple class/objects.

However, I got stuck on the testing aspects of the microservice. With the original design the team had
followed Martin Fowler's recommendations for testing microservices 
(<a href="http://martinfowler.com/articles/microservice-testing/" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fmartinfowler.com%2Farticles%2Fmicroservice-testing%2F\46sa\75D\46sntz\0751\46usg\75AFQjCNGBQEurXP3AGE43tl-1SgF7yn2nsw&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fmartinfowler.com%2Farticles%2Fmicroservice-testing%2F\46sa\75D\46sntz\0751\46usg\75AFQjCNGBQEurXP3AGE43tl-1SgF7yn2nsw&#39;;return true;">http://martinfowler.com/articles/microservice-testing/). This resulted in a lot of testing code to test all the 
HTTP layers from unit tests, integration tests, component tests and finally end-to-end tests). The tests also 
relied heavily on the Mockito framework to mock all the external services which interacted with the microservice.


That's a sure smell: Mocks are useful in any language to abstract away requirements from your components, not constraints. This means the need for mock is driven by usage (interfaces, or typeclasses) and not by implementation (e.g. concrete behaviour of a service). In microservices one could use the consumer-driven contact approach to expose clients' requirements as tests (or specifications) to be fulfilled by providers, e.g. other services.

I simply could not think of how I would or if I needed to do all this testing with my equivalent FP solution.
All I have with my solution is a few functions which I could easily write unit tests for if need be. Do I really
need to write mocks for the external services? I could not find any thing on the internet which deals with
this area. In fact, I think this is an area where FP literature is lacking. We have a lot of literature on FP
theory, FP languages and design techniques, but very little on testing.


Indeed. Most Haskell books are lacking in this respect and I long for a book which would be called Growing Functional Programming Software guided by Tests.

 
I did come across Michael Snoyman's article here (<a href="http://www.yesodweb.com/blog/2012/01/aosa-chapter" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.yesodweb.com%2Fblog%2F2012%2F01%2Faosa-chapter\46sa\75D\46sntz\0751\46usg\75AFQjCNHdk8rUsIbJmwM96lZvS_UIbRE8wA&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.yesodweb.com%2Fblog%2F2012%2F01%2Faosa-chapter\46sa\75D\46sntz\0751\46usg\75AFQjCNHdk8rUsIbJmwM96lZvS_UIbRE8wA&#39;;return true;">http://www.yesodweb.com/blog/2012/01/aosa-chapter) where
he states:

In most dynamically-typed languages, and their web frameworks, the recommended approach to solving this issue is writing unit tests. If you have full test coverage, then running your tests will immediately reveal what code needs to be updated. This is all well and good, but it is a weaker solution than true types:
  • It is all predicated on having full test coverage. This takes extra time, and worse, is boilerplate code that the compiler should be able to do for you.
  • You might be a perfect developer who never forgets to write a test, but can you say the same for every person who will touch your codebase?
  • Even 100% test coverage doesn't guarantee that you really have tested every case. All it's done is proven you've tested every line of code.
Is Michael stating here that there is no need for tests because all the information about the problem is encoded in the types?


I would not speak for Michael. My personal take is that types are great but they can only state static invariants, by construction. They only tell part of the story and are extremely useful, but so are tests. I like to use tests as a way to drive my design, at all level. This means writing the test first and use it to explore and perfect design of the software, including the tests. Then more tests might help refine the behaviour, and possibly the types, of the software.

Regarding your specific problem, an interesting approach you might want to explore is using Monadic QuickCheck.

Best regards,
--
Arnaud Bailly
CTO | 
Capital Match
CapitalMatch
39A ​North Canal Road | Singapore ​059295
+33 617 121 978 | <a href="javascript:" target="_blank" gdf-obfuscated-mailto="EQjsxwrkAQAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">arn...@... | <a href="http://www.capital-match.com" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.capital-match.com\46sa\75D\46sntz\0751\46usg\75AFQjCNHQTo3-NXkUQlhu1x3zOWHnnKW_kQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.capital-match.com\46sa\75D\46sntz\0751\46usg\75AFQjCNHQTo3-NXkUQlhu1x3zOWHnnKW_kQ&#39;;return true;">www.capital-match.com

Capital Match Platform Pte. Ltd., registered in Singapore (Co. Reg. No. 201501788H), is a subsidiary of Capital Match Holdings Pte. Ltd. (Co. Reg. No. 201418682W) (collectively "Capital Match").

This e-mail message and any enclosures are intended only for the person(s) to whom it is addressed and may contain information which is confidential and/or legally protected. Any use, distribution, modification, copying or disclosure by any person(s) other than the named addressee is strictly prohibited. Capital Match disclaims all responsibility from and accept no liability whatsoever for the consequences of any unauthorized person acting, or refraining from acting, on any information contained in this message. If you have received this email in error, please inform us immediately and delete it and all copies from your system.

E-mail transmission cannot be guaranteed to be secure or error-free as information could be intercepted, corrupted, lost, destroyed, arrive later or incomplete, or contain viruses. The sender therefore does not accept liability for any errors or omissions in the contents of this message which arise as a result of e-mail transmission. If verification is required, please request a hard-copy version from the sender. Capital Match makes no representation or warranty as to the absence of viruses in this e-mail or any attachments.

--
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Testing Micro Services

Arnaud Bailly | Capital Match
Hi Mika'il,

I have been a bit laconic in my previous email, let me elaborate a bit.

The idea I was suggesting is known as Model-Based Testing: Using a model of the behaviour your software is supposed to comply with to test it. In the original paper about Monadic QuickCheck (http://www.cse.chalmers.se/~rjmh/Papers/QuickCheckST.ps) the authors show how one can use QuickCheck as a test generator for monadic, e.g. effectful code. It is obvious QuickCheck can be used as a MBT tool for pure code, as the properties you express are indeed a model of (a fragment of) the behaviour of your pure code, the easiest examples being expressing mathematical properties of algrebraic structures like the rules for a Monoid.

For effectful code, properties cannot be expressed "sub specie aeternitatis": They are dependent on the past, the context, the environment... Hence the idea of expressing your software's model as a "trace", e.g. a sequence of operations, you can generate using quickcheck and then test against your code. For example, if you are modelling some payment service that depends on balance of an account, you could generate various sequence of operations expressing the fact a payment can only be accepted if balance of an account is positive. Of course you could also generate a starting state, e.g. accounts with different balances and characteristics, and test various operations against that state, but that's not how things actually work because the state is actually the result of sequences of operations.

HTH
--
Arnaud Bailly
CTO | 
Capital Match
CapitalMatch
39A ​North Canal Road | Singapore ​059295
<a href="tel:%2B33%20617%20121%20978" value="+6594299471" target="_blank">+33 617 121 978 | [hidden email] | www.capital-match.com

Capital Match Platform Pte. Ltd., registered in Singapore (Co. Reg. No. 201501788H), is a subsidiary of Capital Match Holdings Pte. Ltd. (Co. Reg. No. 201418682W) (collectively "Capital Match").

This e-mail message and any enclosures are intended only for the person(s) to whom it is addressed and may contain information which is confidential and/or legally protected. Any use, distribution, modification, copying or disclosure by any person(s) other than the named addressee is strictly prohibited. Capital Match disclaims all responsibility from and accept no liability whatsoever for the consequences of any unauthorized person acting, or refraining from acting, on any information contained in this message. If you have received this email in error, please inform us immediately and delete it and all copies from your system.

E-mail transmission cannot be guaranteed to be secure or error-free as information could be intercepted, corrupted, lost, destroyed, arrive later or incomplete, or contain viruses. The sender therefore does not accept liability for any errors or omissions in the contents of this message which arise as a result of e-mail transmission. If verification is required, please request a hard-copy version from the sender. Capital Match makes no representation or warranty as to the absence of viruses in this e-mail or any attachments.

--
Loading...