Showing posts with label Eclipse. Show all posts
Showing posts with label Eclipse. Show all posts

Wednesday, December 18, 2019

Creating a Coding Story (Coding Stories) with STS or Eclipse

CodingStories.io is a wonderful tool for senior developers to spread the knowledge of craftsmanship through an organization. Here is a good tool chain for doing this with STS/Eclipse:
  • Maven
  • JUnit 5
  • Git
Why Maven? Unless you want to assume all your Coding Stories readers will be using your IDE of choice (or let them work out setting up the dependencies), use Maven to abstract away your IDE for dependency management.
Why JUnit5? Because it's the most modern and is now well integrated into IDEs.
Why Git? Because that's what Coding Stories uses for integration.

Maven

Using STS's wizard, build a Maven project.



The below seems to be the simplest POM type.


Run the maven build and at should successfully build the Maven HelloWorld application.  (See troubleshooting if not.)

Rename the "project" folder per Coding Stories convention.  (I needed to add "-java" onto the end.) Later, this will be our Git repository.


The next section describes how to adjust the POM file and IDE to handle JUnit 5.

JUnit 5

Although IDEs have JUnit 5 integration, many of them default to JUnit 4. The following POM describes how to use JUnit 5 in your Maven project:

<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

 <modelVersion>4.0.0</modelVersion>
 <groupId>biz.agilenoir</groupId>
 <artifactId>helloworldmocking</artifactId>

 <packaging>jar</packaging>
 <version>0.0.1-SNAPSHOT</version>
 <name>TDD going from Hello World to Mocking</name>
 <url>http://AgileNoir.biz</url>

 <dependencies>
  <!--JUnit tests depend on the engine artifact to build-->
  <dependency>
   <groupId>org.junit.jupiter</groupId>
   <artifactId>junit-jupiter-engine</artifactId>
   <version>5.5.2</version>
   <scope>test</scope>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <!-- Maven by default doesn't support Java 13 so the below sets that up -->
    <configuration>
     <source>13</source>
     <target>13</target>
    </configuration>
   </plugin>
   <plugin>
   <artifactId>maven-surefire-plugin</artifactId>
   <version>2.22.2</version>
   </plugin>
  </plugins>
 </build>

</project>


What this does:

  • POM boiler plate: The first paragraph tells XML parsers about the schema to use for validation and declares the namespace.
  • project identity: your project information here
  • package the build as a Jar (required to package it into something)
  • dependencies: JUnit Jupiter is declared here
  • build/plugins: 
    • Maven plugin: 
      • Since I'm building with Java 13, I declare a modern version of the maven plugin to be used when building, 3.8.1 (you see, maven itself is a plugin).  The default maven plugin doesn't support newer versions of Java.
      • Configure the maven plugin to use Java 13
    • Surefire plugin: used to execute unit tests.
Configure the IDE's project to use JUnit 5:

 Add a simple JUnit 5 test to test the configuration and run it from Eclipse.



package biz.agilenoir.helloworldmocking;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class HelloWorldTest {
@Test
void test() {
fail("Not yet implemented");
}
}
 Run the test and observe that it fails.




Run the test from Maven.  Watch the console for the test report.


If you want to see the test pass, make a change, then run the unit test.  All that's left is to configure Git for CodingStories.

By the way: regarding TDD

Check out the Agile Thoughts podcast.  This podcast gets the Confessions Of An Agile Coach's endorsement (naturally, since the same people produce it) of quality materials for developers and teams trying to get coding done in a way that avoids dealing with legacy issues such as bugs and hard to maintain code.  Agile Thoughts has a lot of great TDD conceptual content along with a radio drama about the difficulties to getting a TDD initiative started.  Click the podcast cover below or here for more information.



Configure Git

Using STS, create a Git repository inside your workspace (there is some controversy over whether this is the best use of Git, but as there is controversy and "no one right way" I think it's alright in this case.)




The project now has "badges" for M-maven, J-java, and a little gold storage icon for Git.

Write your Coding Story

Now that your environment is all tested out. It's time to build your coding story.  Follow "how to" at CodingStories to create your story. When you're finished, tell all your software developer friends and co-workers all about it.  Send them links.  Brag to your boss.  You know, socialize your tools to help others.

 XXX Link to my own coding story coming soon to here XXX

Tweet me if you get stuck: @LancerKind

References

https://howtodoinjava.com/junit5/junit5-maven-dependency/
https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html

Troubleshooting

Problem: Maven build gives me the following:

[ERROR] Source option 5 is no longer supported. Use 7 or later.
[ERROR] Target option 5 is no longer supported. Use 7 or later.
[INFO] 2 errors 
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE

Solution:  Maven defaults to Java 1.6 and will default to a version of the maven plugin that won't work with java 9 or higher unless changes are made in "configuration" (https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html).


 Problem: Can't execute unit test in STS


Solution: Click "OK" and setup a run configuration for JUnit 5.



Problem: "$ mvn test" (Maven) doesn't execute find my unit tests.

Solution: Use the Surfire plugin.  See it as the second plugin declared below.



Thursday, May 5, 2016

Asserting like a Hipster

You know the type. For the past year they've been using the latest new programming language that you just discovered yesterday. They have the latest mobile device with the beta OS, and their laptop is loaded out with more experimental tools than a mad scientist's closet. Hipsters! Every team should have one because they keep us pushing for the next "something better." (Image source: Damn it's hard (and expensive) to be an Alabama hipster.)

Years ago new Java language features along with Hamcrest's matcher library created some changes in JUnit 4.4. Although experienced hands are used to reading the assertEquals(expected, butGot) pattern, if you free yourself from tradition, I think you'll agree that combining Hamcrest with Junit makes tests more readable. Click on the below thumbnail and compare the readability of the test on your left versus right. Although you may be used to reading assertEquals(...), which one would your mother find most understandable?
Tap to zoom
Not only does assertThat(...) read better, it has more advanced matching capabilities so you can do in one line what takes several lines of assertEquals(...) or assertTrue(...). (Source: https://github.com/junit-team/junit4/wiki/Assertions)
tap to zoom
And the error messages are readable without having to write your own (See assertTrue versus assertThat, for example.):

tap to zoom

Setting it up

The setup is difficult which is probably why not many use the more expressive assertThat:
  1. The eclipse JUnit plugin ships with a paired down version of Hamcrest which means although you get good API help via examples on the internet, the version with Eclipse sometimes can't do it or the packages are different (for example, can't do assertThat on a double because the paired down Hamcrest lacks the Matchers for doubles.
  2. "Out of the box" Eclipse's content assist (aka: command complete, intelli-sense) feature isn't any help for discovering the Hamcrest Matchers.
  3. assertThat isn't necessary for doing TDD. TDD adopted alone is hard enough so mixing the "doing TDD" with using assertThat means adding yet another barrier to coaching developers to do TDD, so it's skipped as a future refinement to learn.
 To use assertThat, the "hipster tax" must be paid. Let's get started.

Install latest Hamcrest library

 Go get java-hamcrest jar and add it to your project as an external jar library, and add it ahead of JUnit 4 in the build path (otherwise it'll use the "partial" hamcrest library that was added into the JUnit 4 plugin.
The dependencies for using Junit assertThat with Hamcrest Matchers is satisfied. Create a test class and copy paste the below code into your project, and run the test to see if your environment is OK.  The second test won't even compile if you're trying get by with the Hamcrest that came with Eclipse's JUnit plugin.
package foo;
import static org.hamcrest.CoreMatchers.is;
//import static org.hamcrest.Matchers.closeTo;
import static org.junit.Assert.*;
import org.junit.Test;

public class AssertThatTest {
    @Test
    public void assertThat_worksWithHamcrest() {
        int five = 5;
        assertThat(five, is(5));
    }
/*    @Test
    public void assertThat_accessToModernHamcrest() {
        Double five = 5.005d;
        assertThat(five, is(closeTo(5d, .005d)));
    }
    */   
}
You can get started testing, but to make working with Hamcrest enjoyable we need to configure Eclipse.

Configuring Content Assist

Without Content Assist support, using Hamcrest Matchers becomes a productivity suck. Until fixing this, the only recourse is Google or hunting via typing full package names to figuring out what matcher to use.
Out of the box Ecilpse is zero help finding matchers to use with assertThat
Go into Eclipse's Preferences and configure "Favorites" to clue in Content Assist for org.hamcrest.CoreMatchers and org.hamcrest.Matchers.





 Afterwards, Eclipse will give you a helping hand, and at this point the hipster tax has largely been paid (anyone know anyone at Eclipse Foundation who is positioned to fix this so it works out of the box?):
Think "is" for comparing a single something. Think "has" when comparing an array or collection to a single or collection of somethings

You'll be able to do more with less code, and that's a beautiful thing. The following is a taste of the Matcher menu: collections, string comparisons, iteratable objects, time comparison.




Done

After this, you can assertThat(you, is(hipster_cool)). Better get started though. Because soon everyone will be doing it and assertThat won't be hip any longer 'cause it'll be mainstream. For background on why you'd want to write micro tests, use your commute time to listen to the Agile Thoughts podcast series about the Test Automation Pyramid, episodes 1 through 8.  Each episode is short, to the point, and entertaining.
Episodes 1 through 8

Now get 'er done hipster!

Troubleshooting

If you don't change the project dependency order so that java-hamcrest is before JUnit 4, you'll get the following exception during test execution because of a compatibility issue when trying to use Eclipse's JUnit plugin's older/partial Hamcrest:
Select to zoom.

References

http://edgibbs.com/junit-4-with-hamcrest/

http://stackoverflow.com/questions/2922879/best-way-to-unit-test-collection 

http://stackoverflow.com/questions/21624592/hamcrest-compare-collections