Where Can I Get an Emission Test Near New Hope Road

Road to Simplicity: Tests Are Not Tests [Part Two]

Road to Simplicity: Tests Are Not Tests [Part Two] is the second part of a series on hexagonal architecture. The goal of the series is to express a methodology to reach simplicity. In this series I use a demo project to express concretely these ideas. The project is written in Java 11 with reactive programming thanks to ReactiveX. The software analyzes the capabilities (e.g. java version) of the machine. Then it will expose them through REST API. In reality I write use case and its test simultaneously. These tests are crucial because use cases represents what our software does.

image

Raffaele Florio Hacker Noon profile picture

@ raffaeleflorio

Raffaele Florio

🪐 Abstractions explorer in love with object-oriented programming

This is the second story of Road to Simplicity. And it's about the role of tests in software writing.

(The first part is about the goal of the series and hexagonal architecture)

Test and correctness

I think that it's inappropriate to associate test with verification of correctness. After all with a test we can verify that a software module (e.g. a function) returns an expected output with a given input. But we cannot prove correctness in this way. We can prove correctness mathematically. And this is what we do to prove algorithms correctness.

We can see tests as experiments on the software system. And the below quote expresses concisely the above concept:

No amount of experimentation can ever prove me right;
a single experiment can prove me wrong

Albert Einstein

So, at most, a test could prove wrongness…

Fear of change

Software aren't static system. They are in evolution. We can add or
delete a feature. We can change its structure. And it changes according the solved problem. There are a lot of reason to change.

However, with an evolution, we can break something that worked in the past. This event is called regression. Eventually we can find regressions manually. But this is a bad road because we could change:

  • a software with a lot of use case. So this method is not efficient;
  • a software that we didn't write. So we didn't know every aspect;
  • a software that we wrote a long time ago. So we could forget some aspect.

For these reasons we need a tool that guarantees to us non-regression. This tool is test.

Tests free us from the fear of change. Indeed if a test fail we can investigate and fix the issues. Otherwise we can rest assured: we didn't break something that worked in the past. This implies code malleability.

This is the most evident advantage. But there is another subtler.

Yourself as client of yourself

The goal of Road to Simplicity is to express a methodology to reach simplicity. And there is a connection with tests.

In the last story we already defined a use case. In reality I write use case and its test simultaneously.

These tests are crucial because use cases represents what our software does. And they guarantees simplicity because when we write tests we're the client of ourselves. And, as programmers, we love simple and clean interface. Furthermore, because test is more code, we don't want to write unnecessary lines. In this way we are forced to write the most minimal and simplest interface.

Code

In this series I use a demo project to express concretely these ideas. It's written in Java 11 with reactive programming thanks to ReactiveX. The project is hosted on github.

The software analyzes the capabilities (e.g. java version) of the machine. Then it will expose them through REST API.

In the previous part we expressed our use case (GetCapabilitiesUseCase) as:

                                  public                                      interface                    GetCapabilitiesUseCase                  {                  Single<Capabilities>                    getCapabilities                    ()                  ; }                              

So here the first test definition. I'm using JUnit 5 with ReactiveX test facility. It verifies that the returned capabilities object is correct. We are passing to the use case factory two mocked port out implementations:

                                                      class                    GetCapabilitiesUseCaseTest                  {                  @Test                                      void                    ok                    ()                    throws                    Throwable                  {     String javaVersion = randomString();     Long networkSpeed = randomLong();     GetCapabilitiesUseCase useCase = UseCaseFactory.getCapabilitiesUseCase(       () -> Single.just(javaVersion),       () -> Single.just(networkSpeed)     );      TestObserver<Capabilities> useCaseObserver = useCase       .getCapabilities()       .test();     assertTrue(useCaseObserver.await(100, TimeUnit.MILLISECONDS));      useCaseObserver       .assertResult(new                  Capabilities(javaVersion, networkSpeed));   }                                      private                    String                    randomString                    ()                  {                  return                  UUID.randomUUID().toString();   }                                      private                    Long                    randomLong                    ()                  {                  return                  ThreadLocalRandom.current().nextLong();   } }              

During the writing I discovered that there is a room of improvement. Currently our use case could return negative network speed.

This is possible because the Capabilities class allows these values. So I improved its constructor with an exception:

                                  @Value                  @Builder                  public                                      class                    Capabilities                  {                                      public                    Capabilities                    (String javaVersion, Long networkSpeed)                  {                  this.javaVersion = javaVersion;                  this.networkSpeed = networkSpeed;                  if                  (this.networkSpeed <                  0L)                  throw                  new                  IllegalArgumentException("Network speed should be greater than 0!");   }                  private                  final                  String javaVersion;                  private                  final                  Long networkSpeed; }              

Then I added the test class about Capabilities:

                                                      class                    CapabilitiesTest                  {                  @Test                                      void                    with_negative_network_speed                    ()                    throws                    Throwable                  {     String javaVersion = randomString();     Long networkSpeed = randomNegativeLong();                  try                  {                  new                  Capabilities(javaVersion, networkSpeed);                  throw                  new                  IllegalStateException("Invalid capabilities built!");     }                  catch                  (IllegalArgumentException e) {     }   }                                      private                    String                    randomString                    ()                  {                  return                  UUID.randomUUID().toString();   }                                      private                    Long                    randomNegativeLong                    ()                  {                  return                  ThreadLocalRandom.current().nextLong(1L, Long.MAX_VALUE) * -1L;   } }              

And I updated the use case test:

                                                      class                    GetCapabilitiesUseCaseTest                  {                  @Test                                      void                    ok                    ()                    throws                    Throwable                  {     String javaVersion = randomString();     Long networkSpeed = randomNonNegativeLong();     GetCapabilitiesUseCase useCase = UseCaseFactory.getCapabilitiesUseCase(       () -> Single.just(javaVersion),       () -> Single.just(networkSpeed)     );      TestObserver<Capabilities> useCaseObserver = useCase       .getCapabilities()       .test();     assertTrue(useCaseObserver.await(100, TimeUnit.MILLISECONDS));      useCaseObserver       .assertResult(new                  Capabilities(javaVersion, networkSpeed));   }                                      private                    String                    randomString                    ()                  {                  return                  UUID.randomUUID().toString();   }                                      private                    Long                    randomNonNegativeLong                    ()                  {                  return                  ThreadLocalRandom.current().nextLong(0L, Integer.MAX_VALUE);   } }              

I run the tests and they are successful.

At this point we can extend our domain without fear of regressions. We have tests that protect us. Furthermore we have a neat use case interface.

Conclusion

For this story that's all. I like to stress that tests are not for the present. We are not verifying with them software correctness. Tests are for the future because they guarantee malleability, extensibility and maintainability. At the end they guarantee code simplicity.

Stay tuned! :D

Resources

  • JUnit 5
  • ReactiveX
  • Test Driven Development
  • Monkey Testing

Tags

# software-testing# architecture# java# test-driven-development# software-development# road-to-simplicity# tests-are-not-tests# hackernoon-top-story# web-monetization

Where Can I Get an Emission Test Near New Hope Road

Source: https://hackernoon.com/road-to-simplicity-tests-are-not-tests-part-two-y6n3e7j

0 Response to "Where Can I Get an Emission Test Near New Hope Road"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel