My Simple Java Logger

16 May

Captain's log...

While working on a recent project using parameterized tests against 1000+ lines of test data, it quickly became clear that some sort of logging was in order to get all the errors in one place in one file. I knew there were solutions such as log4j readily available, but I felt that the setup for that might be a bit too complex and would slow down an effort that was otherwise going quite smoothly.

So I searched the web to get an idea of the best approach for simply writing data to a file. I was able to put that together fairly quickly but then ran into the issue of how best to implement it, either as a method within the test class itself or as a separate class which would then be called by the test class (and any other future test classes which might want to use it). The first option was clearly the easiest and the second was clearly the most sensible.

So I went for both, of course!

While implementing the basic logging as method in my test class, I ran into questions as to how best to initialize the output file, how to append new data to the old without trouncing the file each time, adding a nice separator between each test case and so on. I finally got it sorted out to my liking after which I made the move to putting it into a class of it’s own. Fully acknowledging plenty of help from ‘anonymous donors’ on the Web, here are the results:

import java.io.*;

public class Logger {
    public static String logFileName;

    public Logger (String filename) throws IOException {
        this.logFileName = filename;
    }

    public void initLog(String fileName) throws IOException {
        // initialize log file and delete existing
        File logFile = new File(fileName);
        logFile.delete();
    }

    public void logThis(String message) {

        BufferedWriter bw = null;

        try {
            bw = new BufferedWriter(new FileWriter(this.logFileName, true));
            bw.write(message);
            bw.newLine();
            bw.flush();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {                       // always close the file
            if (bw != null) try {
                bw.close();
            } catch (IOException ioe2) {
                // just ignore it
            }
        } // end try/catch/finally

    } // end method()

    public void logSeparator() {
        String separator = "------------------------------\n";
        logThis(separator);
    }

}

To implement the code from another file, you first need to instantiate an object and (if you like) define a variable to hold the log file name:

public static Logger logger;
public static String logFileName = "ExampleLoginsParameterizedTest.log";

Then, in my JUnit @BeforeClass method, I fully instantiate and initialize the logger:

@BeforeClass
public static void startLogger() throws IOException {
    // instantiate logger
    logger = new Logger(logFileName);
    // initialize new log
    logger.initLog(logFileName);
}

The first line hits the Logger constructor with the logFileName text variable, while the second calls the ‘initLog’ method with the same variable name to clobber the old log if it exists. The old log is clobbered in a way that would make Rube Goldberg beam with pride. The Logger class creates a file with the desired name and then deletes it. If a file with the same name exists, then that file ends up deleted. If it doesn’t, then a file is quickly created and deleted, no harm no foul. There’s probably a much better way to do this, but that’s what I came up with on short notice.

The actual act of logging looks like this:

// log test info and separator to log.txt file AND log to console
message = "Testing: (" + this.UserType + ") " + this.Username
        + "/" + this.Password + ", " + this.SchoolID + "\n";
System.out.println(message);
logger.logSeparator();
logger.logThis(message);

That code appears in my JUnit @Before method, which runs before each test. In this case it puts a separator and then writes some basic info about the test in question.

In another area of the test class, I use the logger to record pertinent details if a try/catch loop fails:

try {
        wait.until(ExpectedConditions.presenceOfElementLocated(By.linkText("Log out")));
    }
    catch (TimeoutException timeout) {
        // log error to log.txt file AND log to console
        message = ">>>ERROR:  Login for " + this.Username + "/" + this.Password
                + " appears to be unsuccessful, 'Log out' link never appeared.\n"
                + "Error text: \n" + timeout + "\n";
        System.out.println(message);
        logger.logThis(message);
    }

That’s it. A poor man’s logger that does what I need and very little more!

Advertisements

Comments are welcome!

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: