Everything apart from 3 class variables were written before the tests were written, does that mean I'm technically not following TDD?
If you are writing any "real" code before you have a test that needs it, then you aren't following TDD. That can be OK - TDD isn't necessarily the best tool to use in all situations. But when you are in a situation where TDD makes sense, then the test is written first.
am I supposed to write the entire test for an unimplemented method first, then create the method and functionality so the tests pass?
It depends on whose guidance you are following. Robert Martin advises that you write just enough of the test for it to fail, and then make that much pass, then write more test, then make that pass, and so on, until the test is complete. He called this the nano cycle. Martin suggested this as a technique for reproducing the experience of working with Kent Beck.
However, when Kent Beck himself describes TDD, he talks about writing one complete test, and then fixing the problems in it one at a time.
I myself find that Beck's style works better for me, especially in a coding environment that can automatically fill some of the missing code. So I'll concentrate exclusively on the design of the test until I am satisfied with it, then let the IDE create the skeleton code I will need to pass the test, and the finally fill in the details.
Is my main objective following TDD to have every single test pass
Tests are really "mistake detectors"; the objective is to create code that delivers value without mistakes.
One of the benefits of TDD is that the ritual greatly reduces the number of "mistakes" you have to deal with at any one time. And yes, that means that the discipline is that we are almost always in one of two states, either (a) all of the tests we have written are passing, or (b) all except one of the test we have written are passing.
Are tests for a class supposed to number greatly(depending on the size of the class)?
Not necessarily size; complexity might be a better gauge - how many different input classes are there? You will normally need at least one sample from each to ensure that all of the behaviors you need are present.
A common illustration here: imagine a function that takes a Gregorian year as input, and returns true if that year is a leap year. The input classes we care about
- year not divisible by 4
- year divisible by 4, but not by 100
- year divisible by 100, but not by 400
- year divisible by 400
So four "tests"?
can you tell me if I am on the correct path
Hard to say. There are a couple ideas that stand out, however.
Most real work includes both "code that is complicated" and "code that is hard to test". One useful trick is to design your code so that the complicated code is easy to test, and the code that is hard to test is so simple that there are obviously no deficiencies.
"Hard to test" includes behaviors that depend on shared mutable state (like a file system). So we'll often choose designs where the file system code is too simple to break, put all the branching somewhere else, and then thoroughly test the branching code.
Furthermore, test design is a thing. In particular, we normally want to prioritize making the tests easy to understand at a glance. This in turn will often mean that you'll keep all of the code for one test together, rather than having a bunch of "set up" code in one place and your asserts somewhere else.