Repository: locustio/locust

Issue:
Fail ratio calculation for individual requests is incorrect
### Description of issue

The fail ratio for each individual request is incorrect, and doesn't match the total fail ratio.

### Expected behavior

The fail ratio is correct.

### Actual behavior

The fail ratio is incorrect. For example, if 10 out of 10 requests fail, I'd expect the ratio to be 100%, but instead it is 50%.
```
 Name                                                          # reqs      # fails     Avg     Min     Max  |  Median   req/s               
--------------------------------------------------------------------------------------------------------------------------------------------
 GET /                                                             10   10(50.00%)    2014    2009    2021  |    2000    0.75               
--------------------------------------------------------------------------------------------------------------------------------------------
 Total                                                             10  10(100.00%)                                       0.75               
```

### Environment settings

- OS: Windows/Linux
- Python version: 3.6
- Locust version: 0.11.0

### Steps to reproduce (for bug reports)

Create a trivial locustfile.py:

```python

from locust import HttpLocust, TaskSet, task

class UserBehavior(TaskSet):
    @task
    def index(self):
        self.client.get("/")


class WebsiteUser(HttpLocust):
    task_set = UserBehavior
```
Run it against a host that doesn't have a web server running at all:

`locust --host http://localhost --no-web --clients=10 --hatch-rate=2 --run-time=30`

All of the "GET /" requests fail, but the stats (as shown above) have the failure rate at 50% rather than 100%.

I think the problem is at [stats.py:279](https://github.com/locustio/locust/blob/8b17c286034178ba31c6d48b93f29202514f5659/locust/stats.py#L279):

```python
            return float(self.num_failures) / (self.num_requests + self.num_failures)
```
It seems like it ought to be:

```python
            return float(self.num_failures) / (self.num_requests)
```

Maybe at some point `self.num_requests` was only the count of successful requests?

Discussion:

Patch:
diff --git a/locust/stats.py b/locust/stats.py
index 4ba20644..3feacc05 100644
--- a/locust/stats.py
+++ b/locust/stats.py
@@ -276,7 +276,7 @@ class StatsEntry(object):
     @property
     def fail_ratio(self):
         try:
-            return float(self.num_failures) / (self.num_requests + self.num_failures)
+            return float(self.num_failures) / self.num_requests
         except ZeroDivisionError:
             if self.num_failures > 0:
                 return 1.0


Test patch:
diff --git a/locust/test/test_stats.py b/locust/test/test_stats.py
index 4b45aeed..fcfee1cc 100644
--- a/locust/test/test_stats.py
+++ b/locust/test/test_stats.py
@@ -252,6 +252,18 @@ class TestStatsEntryResponseTimesCache(unittest.TestCase):
         ))
 
 
+class TestStatsEntry(unittest.TestCase):
+    def setUp(self, *args, **kwargs):
+        super(TestStatsEntry, self).setUp(*args, **kwargs)
+        self.stats = RequestStats()
+
+    def test_fail_ratio_with_failures(self):
+        s = StatsEntry(self.stats, "/", "GET")
+        s.num_requests = 10
+        s.num_failures = 5
+        self.assertAlmostEqual(s.fail_ratio, 0.5)
+
+
 class TestRequestStatsWithWebserver(WebserverTestCase):
     def test_request_stats_content_length(self):
         class MyLocust(HttpLocust):