It is possible, even easy.  Git being what it is, there are many different ways to do it.
To literally do what you suggested originally:
... squash all of the commits on test-branch before rebasing
is easiest if you do it before running git merge while on branch master.  (I know you didn't list git merge as a command, but you did run git merge in your step 6:
- git pull-> out other people have made changes master
because git pull is just git fetch followed by git merge.)  But it's still pretty easy to do after; we just need to target the correct commit-ID.
Let's make a drawing of the commit graph that you have at step 4:
...<- o <- *            <-- master, origin/master
             \
               A <- B   <-- HEAD=test-branch
What this drawing shows is that there are two labels1 pointing to the commit I marked *, namely master and origin/master.  Commit * points back to commit o which points back to yet more commits: that's the history of branch master.
The label for the branch you created (and are now on, hence the HEAD= part) points to commit B.  Commit B then points to commit A, which points to commit *.  That's the history of branch test-branch: you created it when at *, then added A, then added B.
Here are two ways you can easily squash commits A and B at this point:
- git rebase -i master
 - This gives you an interactive edit session where you can "pick" the first commit and then "squash" the second, and it will gather together both commit messages and let you edit the result, in the usual way.  It then makes a (single) new commit whose tree is that of commit - B.
 
- git reset --soft master; git commit
 - This does not open an interactive edit session for the rebase: it just keeps the staging-area-and-tree from commit - B(that's the- --softpart of- git reset --soft), moves the label- test-branchback to point to commit- *directly (that's the- git resetpart of- git reset --soft), and makes a new commit as usual (- git commit).
 - The drawback is that you have to compose a new commit message, but you can recover the commit message from commit - Aor- Bin any number of ways.  For instance, you can use the- -cor- -Cflag to- git commit(you'd have to identify commit- Aor- B, e.g., using- @{1}or- @{1}^or- @{yesterday}or some other reflog specifier).  Or, before doing the- git reset --soft, you can use- git logand save the log message(s) in a file, or whatever.
 - (This second method shines when instead of just two commits to squash, you have 42 or so.) 
Both of these methods really do the same thing: they add a new commit (let's call it AB), leaving A and B behind and kind of greyed-out, which I can't really draw correctly:
              AB        <-- HEAD=test-branch
             /
...<- o <- *            <-- master, origin/master
             \
               A <- B   [ghost version of test-branch]
The ghost-version of your branch is invisible to most normal usage, and eventually (after 30 days or so by default) is garbage-collected away.  (Until then it's still in your repository, and in your reflogs, so that you can find original commits A and B in case you need them after all.)
What if you've already done step 6?  In that case, you must still identify commit *.  You can do it the way jsexpert suggested while I was writing this up, or you can find it with git merge-base:
$ mergebase=$(git merge-base HEAD master)
# then pick just ONE of the next two
$ git rebase -i $mergebase
$ git reset --soft $mergebase; git commit
Here's how this works.  After git checkout master; git fetch; git merge; git checkout test-branch (steps 5 and 6, more or less), your commit-graph now looks more like this:
...<- o <- * <- o       <-- master, origin/master
             \
               A <- B   <-- HEAD=test-branch
That new o commit that master and origin/master are pointing to—or it may be a whole chain of commits—are "in the way", but the "merge base" of test-branch (where you are now) and master is commit *: the nearest shared commit before the two branches diverge.
We then simply target the rebase or reset --soft at that commit.  When we're done and have a single new AB commit, it looks like this:
              AB        <-- HEAD=test-branch
             /
...<- o <- * <- o       <-- master, origin/master
             \
               A <- B   [ghost version of test-branch]
Once you have the squashed AB commit, you can then git rebase that onto master in the usual way.
Note that the other answer is doing exactly the same thing, it's just identifying commit * by counting commits.  If you know there are two commits between the tip of test-branch and the "interesting" commit *, HEAD~2 identifies the same commit as $(git merge-base HEAD master).  Using git merge-base just allows you to avoid counting.
1"References" is the actual general git term.  In this case they're branch names, and I am using the word "label" to distinguish them from the branch history formed by this commit graph.  The word "branch" in git is used to refer to at least these two different things, and it gets confusing.