I have next task:

There is a file with two words with the same length. Call them first and last.<br>
Also there is a file - dictionary with a lot of different words.<br>

The task is to find shortest chain of words from dictionary from first word to last so that two neighbouring words different just one character. All words of chain must be the same length.

for example:

input:

// fist and last words

    top
    son

// dictionary

    top
    son
    pop
    pot
    dot
    ton
    son
    soft
    task

output:

    top
    ton
    son

My programm works, but i am not sure that it is not a shit code. So I ask you to view my code. I also have to  make Junit tests, but  i haven't used it before. So ask you to show how can i test this via Junit. Thanks :) 

    public class Main {

	// args[0] - is path to file with first and last words
	// args[1] - is path to file with dictionary
	public static void main(String[] args) {
		try {
			List<String> firstLastWords = FileParser.getWords(args[0]);
			// System.out.println(firstLastWords);
			int sizeOfWords = firstLastWords.get(1).length();

			List<String> dictionary = WordHandler.getSameLengthWords(
					FileParser.getWords(args[1]), sizeOfWords);
			// System.out.println(dictionary);

			Tree tree = new Tree(dictionary, firstLastWords);
			tree.print();
			tree.findShortestSuitableChain();
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
    }
/////////////////<br>

    public class FileParser {
	public FileParser() {
	}

	final static Charset ENCODING = StandardCharsets.UTF_8;

	public static List<String> getWords(String filePath) throws IOException {
		List<String> list = new ArrayList<String>();
		Path path = Paths.get(filePath);

		try (BufferedReader reader = Files.newBufferedReader(path, ENCODING)) {
			String line = null;
			while ((line = reader.readLine()) != null) {
				String line1 = line.trim().replaceAll("\uFEFF", "");
				list.add(line1);
			}
			reader.close();

			for (int i = 0; i < list.size(); i++) {
				if (list.get(i).length() <= 1) {
					list.remove(i);
				}
			}
		}
		return list;
	}
    }
//////////////<br>

    public class WordHandler {
	public WordHandler() {
	}

	public static boolean isOneLetterDifference(String baseWord,String checkWord) {
		char[] baseChars = baseWord.toCharArray();
		char[] checkChars = checkWord.toCharArray();
		int diffLetters = 0;

		if (baseChars.length != checkChars.length) {
			return false;
		}

		for (int i = 0; i < baseChars.length; i++) {
			if (baseChars[i] != checkChars[i]) {
				diffLetters++;
			}
		}

		if (diffLetters == 1) {
			return true;
		} else {
			return false;
		}
	}

	public static List<String> getSameLengthWords(List<String> list, int length) {
		List<String> list1 = new ArrayList<String>();
		for (String st : list) {
			if (st.length() == length) {
				list1.add(st);
			}
		}
		return list1;
	}
    }    
////////////////<br>

    public class Tree {
	public Tree() {
	}

	public Tree(List<String> dictionary, List<String> firstLastWords) {
		this.dictionary = dictionary;
		this.firstLastWords = firstLastWords;
		this.rootNode = new Node(firstLastWords.get(0), null);
		this.lastWord = firstLastWords.get(1);
		this.buildBranch(rootNode);
	}

	private List<String> dictionary;
	private List<String> firstLastWords;
	private Node rootNode;
	private String lastWord;

	public List<String> getDictionary() {
		return dictionary;
	}

	public void setDictionary(List<String> dictionary) {
		this.dictionary = dictionary;
	}

	public List<String> getFirstLastWords() {
		return firstLastWords;
	}

	public void setFirstLastWords(List<String> firstLastWords) {
		this.firstLastWords = firstLastWords;
	}

	public Node getRootNode() {
		return rootNode;
	}

	public void setRootNode(Node rootNode) {
		this.rootNode = rootNode;
	}

	// sets suitable children of node
	private void writeChildrens(Node node) {
		List<String> currentDictionary = new ArrayList<String>(dictionary);
		// currentDictionary - is dictionary for this current Node
		// currentDictionary = dictionary - (this node data + all data of parent
		// nodes)
		currentDictionary.removeAll(node.returnParentData());
		List<Node> children = new ArrayList<Node>();
		String data = node.getData();

		for (String st : currentDictionary) {
			if (WordHandler.isOneLetterDifference(data, st)) {
				children.add(new Node(st, node));
			}
		}
		node.setChildren(children);
	}

	// build whole tree branch by branch
	private void buildBranch(Node node) {
		writeChildrens(node);
		List<Node> children = node.getChildren();
		if (children.size() > 0) {
			for (Node child : children) {
				buildBranch(child);
			}
		}
	}

	// find all chains of tree, which last node's data = lastWord
	private void findSuitableChains(Node node, Map<Integer, List<String>> map) {
		List<Node> children = node.getChildren();
		if (children.size() > 0) {
			for (Node child : children) {
				if (child.getData().equals(lastWord)) {
					int i = map.size();
					map.put(i, child.returnParentData());
				} else {
					findSuitableChains(child, map);
				}
			}
		}
	}

	// prints whole tree from rootNode
	public void print() {
		rootNode.print();
	}

	// from all suitable chains finds shortest and prints it
	public void findShortestSuitableChain() {
		Map<Integer, List<String>> map = new LinkedHashMap<Integer, List<String>>();
		findSuitableChains(rootNode, map);

		// find index of shortest chain
		int shortChainIndex = 0;
		int dictionarySize = dictionary.size();
		for (Map.Entry<Integer, List<String>> entry : map.entrySet()) {
			if (entry.getValue().size() < dictionarySize) {
				dictionarySize = entry.getValue().size();
				shortChainIndex = entry.getKey();
			}
		}
		Collections.reverse(map.get(shortChainIndex));
		List<String> list = new ArrayList<String>(map.get(shortChainIndex));
		for (String s : list) {
			System.out.println(s);
		}
	}

    }
///////////<br>

    public class Node {

	public Node(String data) {
		this.data = data;
	}

	public Node(String data, Node parent) {
		this.data = data;
		this.parent = parent;
	}

	public Node(String data, Node parent, List<Node> children) {
		this.data = data;
		this.parent = parent;
		this.children = children;
	}

	private String data;
	private Node parent;
	private List<Node> children;

	public String getData() {
		return data;
	}

	public void setData(String data) {
		this.data = data;
	}

	public Node getParent() {
		return parent;
	}

	public void setParent(Node parent) {
		this.parent = parent;
	}

	public List<Node> getChildren() {
		return children;
	}

	public void setChildren(List<Node> children) {
		this.children = children;
	}

	// returns list of strings containing data of node and all parents of node
	// this method is used when we find dictionary of current node
	// (we have to delete words that have been already used upwards in the branch)
	public List<String> returnParentData() {
		Node node = this;
		List<String> list = new ArrayList<String>();
		while (node.getParent() != null) {
			list.add(node.getData());
			node = node.getParent();
			if (node.getParent() == null) {
				list.add(node.getData());
			}
		}
		return list;
	}

	// prints tree from this node
	public void print() {
		print("", true);
	}

	private void print(String prefix, boolean isTail) {
		System.out.println(prefix + (isTail ? "└── " : "├── ") + data);
		for (int i = 0; i < children.size() - 1; i++) {
			children.get(i).print(prefix + (isTail ? "    " : "│   "), false);
		}
		if (children.size() > 0) {
			children.get(children.size() - 1).print(
					prefix + (isTail ? "    " : "│   "), true);
		}
	}

    }

///////////<br>

test with words in example give next: <br>

|-top    

    ├── pop
    │   └── pot
    │       └── dot
    └── ton
        ├── son
        └── son
top<br>
ton<br>
son