Showing posts with label Automation. Show all posts
Showing posts with label Automation. Show all posts

Tuesday, June 3, 2014

About the „Is TDD Dead?“ discussion

It did not take long after Agile died that TDD joined its party. If you havent noticed, David Heinemeier Hansson put up quite a rant against TDD on his blog leading to a lot of discussion - also on Twitter. Finally they ended up doing a live online discussion regularely featuring Kent Beck, Martin Fowler and David not (yet) involving the TDD advocate Robert C. Martin aka uncle bob. If you haven't watched it live, here is the initial 30min discussion of the series on Youtube. I really recommend the whole series.

I think this topic and the ongoing discussion is very valueable to our craft because it is the kind of questioning and critical thinking that evolve what we do and how good we are at it. Even if we have a strong faith in something, we should not be afraid to question it, ever.

I get davids points, however i do not entirely agree with all of his concerns. I want to share my thoughts in this blogpost.

„Test induced design damage“
A good design is a design that makes the software easy to change. I think this is something we all agree about. While TDD generally puts a lot of good pressure on your design, it can still make the code hard to change if you apply a high level of isolation, lots of mocking, and a high test-granularity. In this case refactorings and other changes will force us to touch a lot of test-code also. So i've come to the conclusion that its best to apply an individual level of test-isolation/granularity that suit the current requirements. Complex and/or long-lived software might take much value of a strict TDD approach, while simple and/or short-lived software might take more value of a more pragmatic approach. I've happened to experience lots of applications that were so big yet simple that "collaborating-units-tests" with reduced mocking and integration tests were just perfect. The value of this approach was that it was very easy to change/refactor production code without touching test-code. Still, the tests provided 100% functional coverage. So i think that design damage is not induced by tests or tdd, but by bad decisionmaking. Testing is engineering. Look for advantages, make tradeoffs. Trying to minimize mocking can definitely pay off. The advantages of a high test-isolation-level/granularity are
  • a very accurate fault-feedback,
  • and that every part of the code is executed just as much as it had to, leading to a faster test-suite

„To Test first, or not to Test first“
The point is, you do not want to verify if the code is working manually. You'd have to do it way too often, and it would just take too long. You want to be able to fiddle with the code, and do small changes frequently, without having to try everything out manually. You want to do it automated, and the feedback should be instant. So i see no point in 1. writing code, 2. trying it out, and then 3. writing a test. Why not write the test in the first place? Also, we tend to be very flaccid on writing a test for something that we have found to be working, because we tend to become euphoric about our success very quickly which makes us tired of digging in details. Other than that, the actual writing of the test first forces us to think about the problem to an extent that makes us recognize details, that we hadn't yet thought of. These details are better to be known before we start writing production code.

„TDD is so widespread nowadays“
I was laughing when i noticed that there are actually people who believe that everyone does tdd nowadays. Sadly, TDD, or lets say developer testing is in fact unused and/or undiscovered in many places. I've happened to see it missed in programming education and also software companies. Sometimes, it was even unwelcome by certain customers. If you were using any kind of developer testing in these places, you were a pioneer. There is still plenty of work to do on this topic.

The bottom line is, automated developer testing is good. We need it. We were silly if we didn't. The question is just: "How?". And this is where engineering comes in.

Tuesday, October 15, 2013

Boost your development speed

I'm really pragmatic on this. To go faster, you need to avoid the things that slow you down. These blockers may vary from developer to developer, but some are pretty common. In this post i will elaborate on the more common ones. Before i do so i want to remind you that to improve, we might need to unlearn in the first place.
Tip: Sometimes, the greatest achievement in improving is to successfully unlearn.

Are you using your Mouse?

Don't let your mouse slow you down. If you are not using all of your fingers typing, you might want to stop reading here and go over to a typewriting course. The following recommendation also assumes that you are using a feature rich editor like vim or an ide. Every single time you move your hand over to your mouse for a click there is a keyboard shortcut for the exact action that you are not aware of, or not used to. You want to learn these. It's really not that hard,  you'll get used to it faster than you'd think. Just begin by putting your mouse over to the other (or wrong) side of your keyboard. You're now forcing yourself to think every time you want to click. When this happens, remember to think of a possible solution using your keyboard. Don't know any? Ask your friends or search the internet (yes, you can use your mouse for that). BUT: Do not use your mouse for what ever action you wanted to perform. After following these simple rules for a few days, you'll notice how irrelevant your mouse has become. If you start feeling comfortable using your keyboard only, you could even try some sessions with your mouse plugged out. Mastering your keyboard will significantly boost your development speed.
Tip: You could print out a list of your IDEs shortcuts and use it as a cheatsheet

Reduce the Time debugging

Debugging costs an awful lot. It's not rare that we end up hunting a bug for hours or even days. Quite often we engage multiple co-workers to solve it. This is really not a scenario we want to be in, since its not only expensive, but also depressing. How can we avoid such a scenario? Pretty easy. Just separate the software into pieces that work in isolation, and write automated tests that cover the components behaviour. This way, we can easily distinguish the component the bug is actually sitting in, and the debugging will become a cinch. The better the tests, the easier to find the bug. However, you wont write good tests, if the system that you are testing is already done and working. You'll assume that there is no additional value of writing thoughtout tests, when it's already working. Overcome this dilemma by writing your tests BEFORE the implementation. As a side effect, this will also help you coding in many ways. You want to treat your tests as first class citizens and as what they are - at least as important as your implementation. Think of a blacksmith who's casting metal into a mold. What would be more important for him. The mold, or the first sculpture coming out of it? You know the answer. And guess what... the tests are your mold. I don't care what you call it. TDD, BDD or whatever. Just automate tests to cover your softwares behaviour, write them before the implementation, and treat them as what they are - at least as important as your implementation.
Tip: When using TDD, you want to use a shortcut to quickly navigate between the test and its implementation. I've bound it to Alt+T


Reduce the Time reading code

I can't stress this enough: You spend more time reading code than writing code. Believe it or not, while implementing a new feature or solving a bug, you repeatedly read code. You read code before you start writing new code, you read code multiple times inbetween writing code, and you read code after you have written it. Reading a 50 line method is pretty time consuming. Thus you want to make reading as easy and smooth as possible. Write self explanatory code with good names and short methods. And Don't Repeat Yourself. Who wants to read anything twice? Invest some time on this, and it will pay off.

Improve your search skills

This is an important one. A searchengine has become the most important development tool. It is even more important than your ide. You can do anything without your ide if you can find out how, but you cannot do anything with your ide if you dont know how. You are probably googling regularely, so it's worth improving. Improve your searchterms. Anticipate helpful words like 'how to' or 'problem'. Try different variants and quote important words and sentences. If you keep getting bad results of a common subject or website, filter them out using a preceeding minus. Here are some examples:
  • while c -do -c++
  • SomeException -helpme.com
  • How to "clean code"
If you keep getting out-dated information, limit your search to the last month/year. This can easily be done in the search options. On stackoverflow, do not always read the first post since its usually a question and code thats not working. Scroll down to the answers with the most upvotes. They are worth reading. Bookmark the sites/docs that you are using regularely. You don't want to search them over and over again. Also, consider code search engines (Examples here and here).


Focus & Calm

You want to get into and keep a good focus when working on a task. Get into your flow and do not allow disruptions. Several disruptions can easily cost you an hour or two each day. Use headphones in louder environments, and communicate that you'll be available for questions a little later. Focus requires a clear mind. Make sure you don't have to remember too much stuff. You don't want to be afraid of forgetting things. If you can feel the fear to forget, write that thing down - so you can forget. Also, don't work on too many different tasks/projects at the same time. One is perfect, two is ok. More is probably just slowing you down. I've happened to work on 7 different projects a single day. It's really really dragging from you. Also, stay calm even in the most stressful situation. Huddling just slows you down even more.

Invest in Hardware

Hardware is cheap, workhours are not. Good hardware will save lots of time in the long term. An SSD that makes you boot within seconds and loads everything real quick, saves at least 10 minutes a day which is 40 hours a year. Same goes with ram and cpu of course. Also, screensize really matters. Choose a large monitor to be able to see everything without resizing/scrolling windows/panels. I personally feel comfortable with ~27". You can speed up many tasks using two monitors also. Web development would be such a task for example.
Tip: 16:9 is standard nowadays but not quite optimal for coding. The higher the screen, the more lines of code you see. Try a 16:10 instead.

Optimize your Workflow, Question your Tools

It depends on what you are working on, but the goal stays the same. You want the most lean workflow and you will constantly have to reevaluate and improve it. For example: If you are working on a Java Webapp, you want to be able to quickly get feedback without redeploying. You can do this by using a class-reloader like spring-loaded or JRebel, or use the Play Framework which does not require redeployments at all due to its architecture. You could also question the language. Is there something else than java that could be more appropriate? Automate everything: testing, building, deployment, notifications. Consider rapid prototyping if you are in the early stages of a project.


Thursday, June 13, 2013

What makes a great Developer

Passion

It's the taste of success that comes with every little task that you've mastered, and smart solutions you've found that turn out advantageous. Programming is not just a job, it's an Art - it's Poetry. With Passion comes Motivation and thus Progress. Software development is not only huge, but also evolving very fast. A good developer enjoy's keeping up-to-date, since he knows that there's always a better way to do something. Learning new ways, satisfies his hunger.


Curiosity

A Program is deterministic. There is no such thing as an accident in a computers world. Every effect has its cause. A great developer does not accept accidents. He'd rather search and debug the numerous layers of a Software and it's environment to find the very reason. He builds up deep knowledge by doing that, allowing him to better understand, read and interpret weird behaviour of an application. A good developer does not program by Accident.

“The important thing is not to stop questioning. Curiosity has its own reason for existing.” - Albert Einstein

"The most likely way for the world to be destroyed, most experts agree, is by accident. That's where we come in; we're computer professionals. We cause accidents." - 
Nathaniel Borenstein



Cognition

Programming is the act of solving a problem. Problems can be factorized into multiple parts that work together as a whole. To find and reflect those in your mind, and imagine their interaction is a true skill. There is nothing more to say about that.


Meticulosity

Programming is full pitfalls that can be tracked down to the very microcosm of Software Development. The Devil is in the details, and even the smallest sluttery can easily tear a Project down. That's why perfection is so powerful, and important for high quality and success. If you accept a single flaw, you will most likely accept a second, ... and a third ... until you got a mess. A good developer cannot accept flaws and thus avoids many pitfalls increasing quality. There is an analogy to the Broken Windows Theory, which basically says that a single broken window can easily lead to more serious deviance, crime, abandonment and demolishment of its house.


Time

Greatness comes with experience. It's the iterations of improvement that have been lived through, that really matter. Yes, you can simply follow advices, patterns and best practice. But that has nothing to do with Wisdom, which evolves by doing mistakes and iterations.


Humbleness

A great developer knows that he doesn't, and will never know everything. He knows, that there is always room for improvement, also in his own work. He admits his mistakes and accepts critisism.


Tenacity

A good developer declares war on every workaround. He will fight it even if he has to struggle hour after hour, through the night, until the sun rises. Even the greatest developer meets problems, that he might not consider solvable in the first place. But he takes it as a challenge, unless it's not an antipattern. "It won't work" is not an option. Hard-earned success evolves self-confidence.

Vision

In Software development, it is common to work long times on small tasks. While beeing focused, it's easy to get lost and overlook the impact on the rest of the system. A good developer is skilled in keeping an eye on the bigger picture, foreseeing sideeffects of a current decision. Still he may intentionally choose to postpone their treatment going step-by-step.


Lazyness

This might sound stupid in the first place, but its not. Lazyness leads to a lot of improvements. The probably most important thing it leads to is Automation. Everytime you have successfully refused to do something manually by automating it, you have already improved. Automation is the key to faultlessness, efficiency and progress. Faultlessness, because ideally a computer doesnt make any mistakes (which is not entirely true in every aspect), but humans do real quick. Efficiency, because it's an investment saving time in the long run. The earlier you automate something, the more you get out of it. Progress, because every process that does not demand mental resources anymore leaves room for something else. What you don't have to think of doesn't hinder you, whereas software development is actually completely blown up with barriers that you have to think of all the time.

A good developer is too lazy to
  • write a complete API doc, he lets JavaDoc do the job.
  • format his code properly, he lets his IDE do the job.
  • test a functionality over and over again, so he automates it using xUnit. 
  • read complicated methods, so he writes short readable methods with good names.
  • write the same lines of code all over again. He seeks for ways to refactor to avoid such boilerplate code, since he is too lazy to repeat himself. (DRY)
  • implement that functionality that nobody asked for. (YAGNI)
  • use bitwise shifting for a subtraction, he keeps it simple stupid (KISS).
  • write code at all, he lets his colleague do it for him (Pair Programming).
    Nah, i was just kidding on this one ;-) 

What do you think makes a great developer?

Sunday, March 24, 2013

Automatically generated Class Diagrams using Maven & UMLGraph

Drawing Class Diagrams preemptive is sometimes nice to optimize your thought of design. But it will still most likely change in the development phase. Since your Class Diagram is part of your documentation it should be up to date all the time. There is no point in having a Class Diagram if the code does not fit it. You could keep adapting the changes to the Class Diagram by hand, but that can get very time-consuming and exhausting. You should rather automate that process, and there are several ways to achieve exactly that. You could for example search for a UML Class Diagram Tool supporting roundtrip engineering. There are some commercial, and even some free ones available. Not all of them work very well and it can be a frustrating task to figure out which way to go. You would probably try out some and throw them away because they are just not what you expected.
Thats why i want to show you a different approach: Letting a Javadoc Doclet draw the Class Diagrams in build phase and embed them into your javadoc automatically. UMLGraph is such a doclet. It analyzes your code, draws Class Diagrams automatically and embed them into your javadoc.

Since maven can run javadoc at build phase it's perfect. You just have to configurate the maven-javadoc-plugin to use UMLGraph.

Configurate Maven to use UMLGraph


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<reporting>                                                                              
    <plugins>                                                                            
        <plugin>                                                                         
            <groupId>org.apache.maven.plugins</groupId>                                  
            <artifactId>maven-javadoc-plugin</artifactId>                                
            <version>2.9</version>                                                       
            <configuration>                                                              
                <doclet>org.umlgraph.doclet.UmlGraphDoc</doclet>                         
                <docletArtifact>                                                         
                    <groupId>org.umlgraph</groupId>                                      
                    <artifactId>umlgraph</artifactId>                                    
                    <version>5.6</version>                                               
                </docletArtifact>                                                        
                <additionalparam>-views -all</additionalparam>                           
                <useStandardDocletOptions>true</useStandardDocletOptions>                
            </configuration>                                                             
        </plugin>                                                                        
    </plugins>                                                                           
</reporting>                                                                             

Beware that the javadoc doclet api has changed from jdk 1.6 to jdk 1.7 and most of the online tutorials are outdated because of that. UMLGraph adapted to jdk 1.7 since version 5.5.

If we run mvn site right now, we will just get that error:
java.io.IOException: Cannot run program "dot": java.io.IOException: error=2, No such file or directory 
This means that the program dot was not found which is a part of the graphviz library.
 

Install Graphviz

For UMLGraph to run you need graphviz installed. Go to the Download Page, and choose your package. On linux you could even sudo aptget install graphviz. Beware that you might have to reboot or relogin to use graphviz, because the Systems Path is extended during installation.

First Result

Run mvn site, and open target/site/apidocs/index.html afterwards.


As you can see its drawing beautiful and accurate UML Class Diagrams.

Custom Configuration

If you dont want attributes/methods or other extras you are totally free to configurate those graphs. See Class Diagram Options. Just add them to the
<additionalparam>-views -all</additionalparam>
tag in pom.xml

Saturday, March 2, 2013

Selenium Test Automation with Maven

Today i want to help you manage your Automated GUI Tests (Selenium) better. In the past i have seen many different ways people handle this. Some people just write those plain HTML TestCases with Selenium-IDE, store it somewhere on the HDD and run manually when needed. Others dont even use Selenium-IDE. They write pure Java for Example, and automate their execution with JUnit. My todays solution lies inbetween.

Precondition

  • I want plain HTML TestCases, created with Selenium-IDE. So that someone with little Programming skills can still create them.
  • I want these GUI Tests to be run automatically in my Build process, so my CI-Tool can notify me on errors.
  • I also want all TestCases under Versioncontrol in my Projects Repository since the Tests grow with the Source.
  • I want the most little effort with the highest outcome. So i dont want to export JUnit Tests out of my HTML TestCases since it would be kind of a Duplication - and i want to stick to the DRY Principle.

Solution

First of all i create a Folder in my Project for the Selenium-Tests.

Folder Structure
        1. TestSuite
        2. SomeTest1
        3. SomeTest2
  1. pom.xml

Example TestSuite

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta content="text/html; charset=UTF-8" http-equiv="content-type"/>
    <title>Test Suite</title>
</head>
<body>
<table id="suiteTable" cellpadding="1" cellspacing="1" border="1" class="selenium">
    <tbody>
    <tr>
        <td><b>Test Suite</b></td>
    </tr>
    <tr>
        <td><a href="./SomeTest1.html">SomeTest1</a></td>
    </tr>
    <tr>
        <td><a href="./SomeTest2.html">SomeTest2</a></td>
    </tr>
    </tbody>
</table>
</body>
</html>

 

Example Test

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <link rel="selenium.base" href=""/>
    <title>SomeTest1.html</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
    <thead>
    <tr>
        <td rowspan="1" colspan="3">SomeTest1</td>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>open</td>
        <td>/</td>
        <td></td>
    </tr>
    <tr>
        <td>waitForElementPresent</td>
        <td>//div[@id='someId']</td>
        <td></td>
    </tr>
    <tr>
        <td>click</td>
        <td>css=button.create</td>
        <td></td>
    </tr>
    <!-- Some Steps -->
    <tr>
        <td>assertText</td>
        <td>
            //div[@id='someId']
        </td>
        <td>${expectedText}</td>
    </tr>
    </tbody>
</table>
</body>
</html>

 

Setup WebServer

So i have my TestSuite in place. But how do i run them? Most importantly, it should run within the Maven Build Process, so it will also run on Jenkins-CI or whatever. As we are testing against a real running WebApp this is an End-to-End-Test per definition. In Maven we have the opportunity to run such Tests within the integration-test Phase. If you want to learn more about the Maven Build Life-cycle and its phases check out this. So we need some kind of WebServer to run our WebApp, otherwise the tests wont work. The WebServer should be started before the integration-test phase, and be stopped afterwards. We could Use Tomcat7 or Jetty for example. In this example i will use the tomcat7-maven-plugin. I configure my pom.xml to start Tomcat7 pre-integration-test.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.0</version>
    <executions>
        <execution>
            <id>tomcat-run</id>
            <goals>
                <goal>run-war-only</goal>
            </goals>
            <phase>pre-integration-test</phase>
            <configuration>
                <port>8080</port>
                <fork>true</fork>
            </configuration>
        </execution>
        <execution>
            <id>tomcat-shutdown</id>
            <goals>
                <goal>shutdown</goal>
            </goals>
            <phase>post-integration-test</phase>
        </execution>
    </executions>
</plugin>

If you are running multiple Projects on a CI-Server you might consider using a different Port-Number for each Project.

Finally: Run the Tests

Last but not least we need to run the tests. Luckily there is this selenium-maven-plugin available that does the job.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>selenium-maven-plugin</artifactId>
    <version>2.3</version>
    <configuration>
        <browser>*firefox</browser>
        <suite>src/test/selenium/TestSuite.html</suite>
        <startURL>http://localhost:8080</startURL>
    </configuration>
    <executions>
        <execution>
            <id>run-selenium-tests</id>
            <phase>integration-test</phase>
            <goals>
                <goal>selenese</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Now,  whenever we execute mvn clean verify or even mvn clean install in console, the Tests are run and reports are stored within the target directory. This will also be done by your CI-Tool.

Conclusion

We do have a complete and clean Setup.
  • We have a place to store our Tests,  
  • They are within the Sourcecode and Version control
  • They can be run automatically by CI-Tools
  • Even Non-developers can add new TestCases
Btw: Dont give up if something is not working as intended. Selenium seems a little buggy, and some times you have to dig a little to solve problems. But it really works, i figured it out.
I hope you enjoyed this Guide. Greetings.