You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Part 4 - Concurrency/2. Testing Rx.md
+10-10Lines changed: 10 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,19 +1,19 @@
1
1
# Testing
2
2
3
-
When designing any system, you also want to test it to guarantee its quality and that this quality does not regress as the system is modified throughout its lifetime. Ideally, you want to automate the process of testing it. Modern software is backed by thorough unit tests and Rx code should be no different.
3
+
When designing any system, you want guarantees about the correctness of the operations and that this quality does not regress as the system is modified throughout its lifetime. You'll design tests, which, ideally, should be automated. Modern software is backed by thorough unit tests and Rx code should be no different.
4
4
5
5
Testing a synchronous piece of Rx code is as straight-forward as any unit test you are likely to find, using predefined sequences and [inspection](/Part 2 - Sequence Basics/3. Inspection.md). But what about asynchronous code? Consider testing the following piece of code:
6
6
```java
7
7
Observable.interval(1, TimeUnit.SECONDS)
8
8
.take(5)
9
9
```
10
-
That is a sequence that takes 5 seconds to complete. That means every test that uses it will also take 5 seconds or more. That's not convenient at all if you have thousands of tests to run.
10
+
That is a sequence that takes 5 seconds to complete. That means every test that uses this sequence will take 5 seconds or more. That's not convenient at all, if you have thousands of tests to run.
11
11
12
12
## TestScheduler
13
13
14
-
The piece of code above isn't just timeconsuming, it actually wastes all that time waiting for time to pass. If you could fast-forward the clock, that sequence would be evaluated almost instantly. Well, you can't fast-forward your system's clock, but Rx sees time through its schedulers. You can have a scheduler that virtualises time, called `TestScheduler`.
14
+
The piece of code above isn't just time-consuming, it actually wastes all of that time doing nothing while waiting. If you could fast-forward the clock, that sequence would be evaluated almost instantly. You can't actually fast-forward your system's clock, but you can fast-forward a virtualised clock. It was a design decision in Rx to only use time through schedulers. This decision allows you to replace real time with a scheduler that virtualises time, called `TestScheduler`.
15
15
16
-
The `TestScheduler` does scheduling in the same way as the schedulers that we saw in the chapter about [Scheduling and threading](/Part 4 - Concurrency/1. Scheduling and threading.md). It schedules actions to be executed either immediately or in the future. The difference is that time is frozen and only progresses upon request.
16
+
The `TestScheduler` does scheduling in the same way as the schedulers that we saw in the chapter about [Scheduling and threading](/Part 4 - Concurrency/1. Scheduling and threading.md). It schedules actions to be executed either immediately or in the future. The difference is that time is frozen and only progresses upon request. We decide when time progresses and by how much.
17
17
18
18
### advanceTimeTo
19
19
@@ -56,9 +56,9 @@ Advancing to 40s
56
56
Virtual time: 40000
57
57
```
58
58
59
-
We scheduled 3 tasks: one to be executed immediately, and two to be executed in the future. Nothing happens until we advance time, including tasks scheduled immediately. When we advance time, tasks are executed from the queue, until a task that is not ready yet.
59
+
We scheduled 3 tasks: one to be executed immediately, and two to be executed in the future. Nothing happens until we advance time, including the tasks scheduled immediately. When we advance time, the scheduler synchronously executes all the tasks that were scheduled for that period of time, in the order of the time they were scheduled for.
60
60
61
-
You can even set time to a previous moment than the one you are now. That isn't a useful feature as much as a source of bugs in your tests. Usually, `advanceTimeBy` will be closer to what you want to do.
61
+
`advanceTimeTo` allows you to set time to any value, including one that is before the current time. This implementation decision can needlessly introduce bugs in the tests, so it is probably better to use the next method, when applicable.
62
62
63
63
### advanceTimeBy
64
64
@@ -151,7 +151,7 @@ Third
151
151
152
152
## Testing
153
153
154
-
Rx operators involving asynchronous actions, schedule those actions using a scheduler. If you take a look on all the operators in [Observable](http://reactivex.io/RxJava/javadoc/rx/Observable.html), you will see that such operators have overloads that take a scheduler. This is the way that you can supplement their real-time default schedulers for your `TestScheduler`.
154
+
Rx operators which involve asynchronous actions schedule those actions using a scheduler. If you take a look at all the operators in [Observable](http://reactivex.io/RxJava/javadoc/rx/Observable.html), you will see that such operators have overloads that take a scheduler. This is the way that you can supplement their real-time schedulers for your `TestScheduler`.
155
155
156
156
Here is an example where we will test the output of `Observable.interval` against what we expect it to emit.
157
157
@@ -171,12 +171,12 @@ public void test() {
171
171
}
172
172
```
173
173
174
-
This is useful for testing small, self-contained pieces of Rx code, such as custom operators. A complete system may be using schedulers on its own, thus defeating our virtual time. [Lee Campbell suggests](http://www.introtorx.com/Content/v1.0.10621.0/16_TestingRx.html#TestingRx) abstracting over Rx's scheduler factories (`Schedulers`), with a provider of our own. When in debug-mode, our custom scheduler factory will replace all schedulers with a `TestScheduler`, which we will then use to control time throughout our system.
174
+
This is useful for testing small, self-contained pieces of Rx code, such as custom operators. A complete system may be using schedulers on its own, thus defeating our virtual time. [Lee Campbell suggested](http://www.introtorx.com/Content/v1.0.10621.0/16_TestingRx.html#TestingRx) abstracting over Rx's scheduler factories (`Schedulers`), with a provider of our own. When in debug-mode, our custom scheduler factory will replace all schedulers with a `TestScheduler`, which we will then use to control time throughout our system.
175
175
176
176
177
177
### TestSubscriber
178
178
179
-
In the test above, we manually collected the values emitted and compared them against what we expected. This process is common enough in tests that Rx comes packaged with `TestScubscriber`, which will do that for us. It collectes every notification received. With `TestSubscriber` our previous test becomes:
179
+
In the test above, we manually collected the values emitted and compared them against what we expected. This process is common enough in tests that Rx comes packaged with `TestScubscriber`, which will do that for us. Its event handlers will collect every notification received and make them available for us to inspect. With `TestSubscriber` our previous test becomes:
180
180
181
181
```java
182
182
@Test
@@ -213,7 +213,7 @@ void assertTerminalEvent()
213
213
void assertUnsubscribed()
214
214
```
215
215
216
-
There is also a way to block execution until the observable that the `TestSubscriber` is subscribed to terminates.
216
+
There is also a way to block execution until the observable, to which the `TestSubscriber` is subscribed, terminates.
0 commit comments