Testing in the world of SOA (Tue Mar 8, lect 13) | previous | next | slides |

Testing, Unit Testing and special cases in SOA

Logistics

  • Secret code is:
  • Masks may be off if you are tripple vaxed and healthy
  • How did it go with Authentication?

Intro to Automated Testing

  • Unit testing: test a small unit of code that has few side effects
  • Integration testing: test a subsystem that has many components
  • User interface testing: see if the right thing happens when the user takes an action.
  • End-to-end testing: test the complete system from top to bottom

Also Consider

  • Code Coverage: Seeing how much of your actual code is run during a test or production
  • Performance testing: Checking the speed of your code

NB: The Ruby community is especially focused on quality and testing

Why Test?

  • Tests demonstrate that your code actually works!
  • The mental habits needed to write tests parallel exactly those needed to design
  • Testing and developing in parallel tends to surface more bugs early int he development
  • Earlier fix is always cheaper
  • A good test suite can act as a detailed spec
  • A good test suite protects you from regressions
  • It is faster to write code with tests than without it

What to Test

  • Testing is not free!
    1. Code to write
    2. Tests to run
  • As the software (inevitably) evolves
    1. interfaces change
    2. The code changes in two places: implementation and test
    3. Sometimes more: test fixtures, database schemas
    4. Conclusion:
    5. More is not necessarily better

Testing Pyramid

  • From (fewest -> most) tests and brittleness
    1. User Interface tests
    2. Integration tests
    3. Unit Tests

What not to test

  • Try not to test the same thing in more than one place
  • Try not to test a library which is itself well tests
  • Try not to test something that is self-evidently trivial (eye of the beholder)

What to test

  • Try to test code which is prone to off-by-one errors
  • Try to test code with intricate algorithms
  • Try to test to verify assumption

Natural ‘borders’ in the architecture

  • If I check your passport (i.e. validate inputs) at the border
  • Then it makes no sense to check it every time you enter a building
  • As long as there are no unguarded borders :)

About Brittle Tests

  • When a change in design suddenly makes a large number of tests fail
  • Sign that either your design or your test approach can be improved

Background

  • Service testing is key when building a Service Oriented Architecure
  • It is exactly analogous to End-to-end testing or integration testing
  • It supplements basics of Unit Testing
  • It’s an extension of testing in general
  • Concurrent software is the most difficult kind to reason about

External APIs

  • External APIS - Web APIs provided to you by another company altogether
  • You don’t control it. The response time may vary dramatically from test to test
  • You might need tokens or log ins. There may be quotas (maximum number of calls)
  • The service may not be free
  • You need to make sure that your code behaves correctly no matter what that service does
  • You cannot fix bugs in the service, all you can do is respond in a safe way
  • However: We are focused here on *internal” service APIs
  • Since you control that the considerations are different

How Services are put together

  • By definition what makes it a service is that is accessed over HTTP
  • The functionality is invoked via a URL (or queue – for later)
  • And it produces results by returning JSON (or XML – for later)
  • We happen to be using Sinatra for dispatching HTTP routes and returning JSON
  • Usually it’s a good idea to provide a ruby library to invoke the service
  • Keep the app server aspect (e.g. sinatra) as thin as possible
  • Create your functionality from POROs (Poro Service Objects)

Unit Testing Services directly

  • It’s no different from any other automated test
  • Either it invokes the actual URL:

require "faraday"
require "json"

url = "http://dummy.restapiexample.com/api/v1/employees"
data = Faraday.get(url).body
result = JSON.parse(data, symbolize_names: true)
assert_equal :success, result[:status]
  • Or it uses your own provided API library

require_relative xxx
result = get_employees
assert_equal :success, result[:status]

Additional material

Thank you. Questions?  (random Image from picsum.photos)