There are several reasons for this.
First, and most important, note that you are measuring the speed of the connection between you and a particular test server somewhere on the internet. This will be different for each test server, the path between you and the test server (varies with time), the congestion on that path at that particular time, who else on your node is using up bandwidth, how much bandwidth that test server can allocate to your connection, etc.
Also, different speed test implementations use different techniques, for example some open only a single connection, while others (like speedtest.net) open up several parallel connections.
Because of all that, measuring your speed to a distant server over a single connection will be drastically different than testing your speed to a server in your city over several parallel streams. It is the same when browsing the internet, you are dependent on the length of the path, how congested it is, what type of speed the destination server has available to allocate to that one client connection, etc.