MR. Dev

Blog programistyczny.

Programowanie Reaktywne - Bileciki do kontroli - Unit Tests of Interval.


Artykuł ten jest częścią serii artykułów na temat Programowania reaktywnego.

Zapraszam na GitHub-a.

Tematy

  1. Wstęp
  2. Zabawa z czasem - Timer
  3. Kto za tym stoi? - Scheduler
  4. Nie zapominaj - Subscribe
  5. Zabawa z czasem - Interval
  6. Zabawa z czasem - Buffer
  7. Zabawa z czasem - Delay
  8. Zabawa z czasem - Sample
  9. Zabawa z czasem - Throttle
  10. Zabawa z czasem - Timestamp/TimeInterval
  11. Tworzymy dane - Generators
  12. Tworzymy dane - Własna klasa publikująca
  13. Marudzimy - Skip
  14. Marudzimy - Take
  15. Łap To! - ConsoleKey
  16. Kombinatorzy - Concat
  17. Kombinatorzy - Repeat
  18. Kombinatorzy - Start With
  19. Kombinatorzy - Ambiguous
  20. Kombinatorzy - Merge
  21. Kombinatorzy - Zip
  22. Kombinatorzy - Switch
  23. Kombinatorzy - When-And-Then
  24. Kombinatorzy - Combine Latest
  25. Transformers - Select
  26. Transformers - OfType and Cast
  27. Transformers - Metadata
  28. Bileciki do kontroli - Unit Tests of Interval
  29. Bileciki do kontroli - Unit Tests of Observer Interval
  30. Bileciki do kontroli - Unit Tests of Create Cold/Hot Observable
  31. Szpryca - AutoFac

Wstęp

Reactive Extensions - Unit Test Wszystko super i fajnie ale gdzie są testy? Co zrobić by przetestować taki strumień zasilany przez Observable.Interval? Przecież testy będą trwały wieczność… Jest na to rada: przeczytaj post do końca;) Ale na początek warto było by wyposażyć się w dodatkowe narzędzia:

  • Install-Package Shouldly - by asercje były milsze dla oka,
  • Install-Package Microsoft.Reactive.Testing - wymagana biblioteka do testowania Rx-owatych,
  • Install-Package xUnit - bez tej paczuszki to ani rusz w testy;).

TestScheduler

Jak to w testach bywa, trzeba czasem oszukać system i posłużyć się udawaczami. Tak jest i w przypadku testów.

Aby nie odczuć bólu testowania np.: operatora Interval należy zakupić DeLorean-a. I między poszczególnymi porcjami dostarczanymi przez dystrybutora odbyć krótką podróż w czasie…

Jest też inne wyjście prostsze. Po prostu należy użyć schedulera: TestScheduler. Jak tego można dokonać bez posiadania własnego DeLorean-a ukazałem w metodzie InitializeStream.

Przykład oczywiście poniżej oraz w pełnej krasie na GitHub-ie.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class IntervalTestsFixture
{
  #region arrange
  private IObservable<long> _observableInterval;
  private TestScheduler _testScheduler;
  private IList<long> _expectedSequence;
  
  public void PrepareStream(int count)
  {
    InitializeStream(count);

    InitializeExpectedValues(count);
  }

  private void InitializeStream(int count)
  {
    _testScheduler = new TestScheduler();
    var period = TimeSpan.FromSeconds(1);

    _observableInterval = Observable
      .Interval(period, _testScheduler)
      .Take(count);
  }

Reactive Extensions - Test-Driven Development

Jak można było dojrzeć w klasie IntervalTestsFixture zawartych jest więcej interesujących linijek. Dzięki tej klasie możemy wyzbyć się balastu ciężkich do zrozumienia testów jednostkowych. [Chwała Ci za to Procencie:)].

To może coś przetestujemy. Proszę to ładna klaska zawierająca jedną metodę oraz jej wariacje. Testującą czy Interval faktycznie zwraca co ma zwrócić.

Jak widać głównie widzimy to co ma być testowane, a nie to że sąsiadka z naprzeciwka przechadza się nago wieczorami w oknie. Tym się zajmuje wspomniana IntervalTestsFixture. Co by nas zbytnie nie rozpraszało w testowaniu.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class IntervalTests
{
  [Theory]
  [InlineData(0)]
  [InlineData(10)]
  [InlineData(100)]
  [InlineData(1000)]
  [InlineData(100000)]
  public void return_sequence_of_numbers__when__subscribe_to_interval_observable_stream(int count)
  {
    //arrange
    _fixture.PrepareStream(count);

    //act
    var result = act();

    //assert
    _fixture.assert__sequence_of_numbers(result);
  }

  private ICollection<long> act()
  {
    return _fixture.act();
  }

Ładna co nie? Ale to moja:p Napiszcie sobie sami…

Na koniec smaczek co act. Do testów potrzebne są wyniki, dlatego też w miejscu gdzie testujemy funkcjonalność zapisujemy się na strumień, i pakujemy wszystko do listy.

1
2
3
4
5
6
7
8
9
public ICollection<long> act()
{
  var actualValues = new List<long>();

  _observableInterval.Subscribe(actualValues.Add);

  _testScheduler.Start();

  return actualValues;

Potem Shouldly sprawdzi czy wszystko jest prawidłowo. Jak nie to poczęstuje nas odpowiednim i gorzkim komunikatem.

Zakończenie

Testowanie to bardzo ważny aspekt wytarzania oprogramowania. Dlatego zapewne do napisania mam jeszcze wiele postów o podobnej tematyce. Także w kontekście Rx-ów. Jednak na dzisiaj koniec tego dobrego piąteczek, niedługo koniec wyzwania. A ja już czuję ogromną satysfakcję, a co dopiero w Niedzielę:)


Jest to post wchodzący w skład podjętego wyzwania ogłoszonego przez MIROBURN we vlogu z dnia 3 lutego 2018 roku.

Celem wyzwania jest systematyczne działanie w ciągu 30 dni.

Postanowiłem pisać post dziennie o tematyce Programowania Reaktywnego dla platformy .NET.

Wszelkie źródła związane z postami znajdują się na repozytorium GitHub.

Stan obecny wyzwania: 30 z 30 dni.


Referencje:


Wcześniejszy: Programowanie Reaktywne - Transformers - Metadata

Następny: Programowanie Reaktywne - Bileciki do kontroli - Unit Tests of Observer Interval