Haste - mała biblioteka ułatwiająca testy związane z czasem

1

Hej

Z okazji nadmiaru czasu w końcu zabrałem się za realizacje jednego z moich pomysłów i napisać pierwszą wersje (właściwie to coś na kształt PoCa) biblioteki, która dodaje pewnego rodzaje abstrakcje na rzeczy związane z czasem. Jako, że nigdy nie miałem za bardzo umiejętności marketingowych to pokrótce o co chodzi (pełen opis jest w readme na gihubie):

Haste dostarcza interface

public interface TimeService {
    LocalDateTime now();
    ScheduledFuture schedule(Runnable runnable, long delay, TimeUnit timeUnit);
}

z dwoma implementacjami:
-'produkcyjna': działa normalnie w oparciu o systemowy Clock i javowy Scheduler
-'testowa': możliwość dowolnego ustawienia FixedClocka oraz przesuwania czasu w przód (co ważne, przesunięcie czasu odpali wszystkie zaplanowane w międzyczasie zadania)

Pełen opis wraz z przykładami:
https://github.com/krasnoludkolo/haste

Zdaje sobie sprawę, że jest to dopiero pierwsza pre-wersja i nie zawiera za dużo rzeczy. Chodzi mi póki co o jakąś walidację pomysłu przez innych i ewentualne opinie/sugestie, bo plany na przyszłość są ;)

Po co to komu, skoro i tak testuje klasy jednostkowo?
No własnie nie jestem zbytnio fanem tego typu testów. Wole postawić cały system/moduł (maksymalnie bez używania mocków) na czas testu i operować na działającym systemie. Nie wszystkie rzeczy da się wtedy ładnie przetestować (często właśnie rzeczy związanych z czasem, po prostu nie chce się czekać)

0

Zastanawiam się nad tym co dostaje się ekstra w porównaniu do zwykłego java.time.Clock opakowanego w jakieś mniej lub bardziej sprytne wstrzykiwanie (widziałeś jakiś mój przykład w innym wątku).

0

Połączenie tego z schedulerem. Tak, większość projektów tego nie potrzebuje, ale jeśli są jakieś miejsca z planowaniem akcji, zależnościami w czasie itp to wydaję mi się, że byłoby miejsce na 'usystematyzowanie' tego i stworzenie odpowiedniego narzędzia.
Jeśli widzisz jakieś jeszcze rzeczy, które należałoby dodać, jakieś pomysły czy coś to pisz ;)

0

To może wystarczy ograniczyć się do schedulera z zewnętrznie wstrzykiwanym zegarem? Z podawaniem czasu, zarówno prawdziwego jak i symulowanego ta klasa radzi sobie raczej dobrze, problemem są klasy, które są od tych danych zależne, scheduler, który jest w stanie sensownie reagować na podróże w czasie mógłby być przydatny.

0

Zastanawiam się czy api, które biblioteka udostępnia jest odpowiednie. Ja np. korzystam z Clock'a, aby inicjalizować ZonedDateTime, nie korzystam z LocalDateTime. W testach przykrywam to MutableClockiem, które posiada mniej więcej takie samo api jak twoja biblioteka.

0

@piotrpo: tak, ale wykonując 'skok w czasie' trudniej to synchronizować clocki z róznych klas między sobą. Chodzi mi o scenariusz:
1.Dodajesz 3 wydarzenia na 3 kolejne godziny.
2. Przesuwasz czas o tyle aby wszystkie trzy się wykonały
3. Wewnętrzny 'wirtualny' czas schedulera zatrzymuje się na pierwszym zaplanowanym wydarzeniu.
Teraz, jeśli kod który się wykonuje z jakiegoś powodu potrzebuje sprawdzić obecną date to robi się problem. Jeśli cały system będzie korzystał z jednej instancji tego obiektu z biblioteki to pobierając z niego date będzie ona odpowiednio ustawiona przez scheduler. Nie wiem czy rozumiesz o co mi chodzi? ;)

@Aleksander Brzozowski
obecne API to taka trochę biedawersja tego co będzie. Aktualnie zależy mi na tym aby pozbierać opinie i wiedzieć nad czym się skupić w przyszłości. API będzie stopniowo wzbogacane o wszystkie obiekty javowe związane z datami (mam taką nadzieje ;) )

0

Nie masz synchronizować zegarów z różnych klas - potrzebujesz jeden zegar na całą aplikację, tworzony raz, przy jej starcie. W Springu generalnie wystarczy coś takiego:

@Bean(scope=DefaultScopes.SINGLETON)
public Clock createClock(){
  return Clock.systemUTC();
}

A w testach nadpisanie tej konfiguracji + jakaś tam custom implementacja Clock'a. Jak nie używasz żadnego DI, to oczywiście trzeba sobie napisać jakiegoś konfigurowalnego singletona.

0
piotrpo napisał(a):

Nie masz synchronizować zegarów z różnych klas - potrzebujesz jeden zegar na całą aplikację, tworzony raz, przy jej starcie. W Springu generalnie wystarczy coś takiego:

Ale on to dokładnie zrobił.
Tylko bez Springa. I nie żaden tam singleton, normalny obiekt.

I Clock to pikuś. To scheduler jest fajny.

Btw. właśnie dołaczyłem do jednego projektu, bo sam z podobnego czegoś korzystałem tylko za każdym razem w wersji per projetk/klient.
Zobaczymy jak się sprawi.

1

Szybki update

0.0.2
-podczas przeskoku wszystkie zaplanowane zadania mają już prawidłowy czas podczas wykonywania (wcześniej miały czas zakończenia przeskoku)

Dostępna będzie jak tylko maven wszystko przemieli (~2h od teraz)

0

Niestety studia trochę czasu zabierają ;/

0.0.3
-Możliwość zaplanowania callable, a nie tylko runnable

Maven przemieli i będzie.już dostępne. Jeśli macie jakieś pomysły/sugestie co dodać/poprawić to piszcie. Ewentualnie też PRy mogą być ;)

Z najbliższych planów:
-dodać jakaś sensowną obsługę wyjątków(jakoś się postaram to zrobić bez vavra, najwyżej kopiując cześć pomysłów)
-przemyśleć kwestię wielowątkowości
-dodawać kolejne metody do api zwracające inne typy niż tylko LocalDataTime

0

@danek: a nie myślałeś to co chcesz robić podpiąc pod jakąs inną bibliotekę jako jakiś pull request? Wtedy prawdopodobnie będzie to miało większe szanse powodzenia

0

@scibi92: myślałem, ale idea jest, żeby nie tworzyć kolejnej kobyły, a jedynie małą bibliotekę która robi jedną rzecz

0

@scibi92 @jarekr000000
A co myślicie o pomyśle napisania implementacji ScheduledExecutorService oraz Clocka (która nie będzie immutable) przez co łatwiej będzie zaadoptować to do istniejących systemów?

0

@danek:

  1. W jakim celu?
  2. To drugie odpada z ważnego powodu :

Implementation Requirements:
This abstract class must be implemented with care to ensure other classes operate correctly. All implementations that can be instantiated must be final, immutable and thread-safe.

To z javadoc clock'a

A tak poza tym to czemu nie stosujesz klas final? W sumie chyba zrobie pull requesta z poprawkami :P

0

@scibi92: Chodzi o możliwość użycia tej biblioteki w istniejącym projekcie, bez przepisywania pół okolicy.
Co do mutableClocka, ktoś na reddicie zasugerował mi coś takiego

For testing, a MutableClock is invaluable. Case in point - the author of JSR 310, Stephen Colebourne, is also the author of ThreeTen-extra, the library behind MutableClock, so he broke his immutability rule himself. All he's saying is that the clock objects must be safe for use, e.g. you should be able to share a Clock instance safely without the fear 3rd party code will mess with it.

Wydaje mi się, że to może mieć sens.

Co do final to tak, dopiero później dodałem sobie to do template klas i teraz już wszystkie tak domyślnie mam ;)

0

@danek:

  1. Ale juz jakaś implementacja jest i to w Javie 8. Rozumiem że chcesz stworzyć własną, ale jaki jest powód? Co chcesz zmienić w stosunku do ScheduledThreadPoolExecutor ? Bo jeśli jest sensowny powód to nawet chętnie pomoge, Ty masz duzo pracy na uczelni a ja sie moge pobawić ;]
    2.No dobra odnośnie tego clocka mnie zaskoczyłeś?
0

@scibi92: możliwość przesunięcia w czasie podczas testów które odpali wszystkie zaplanowane w międzyczasie zadania, tak aby podczas wykonania tych zadań systemowi wydawało się, że jest godzina odpalenia zadania. Taka jest główna idea i pomysł na Haste ;)

0

@danek:
spullowałem i gdy buduje dostaje takie coś:

Cannot perform signing task ':signArchives' because it has no configured signatory

Po co ten plugin? Ja rozumiem jeszcze jakby był używany przy deploy-owaniu na repo, ale do zwykłeg builda?

0

@scibi92:
Dzięki za zgłoszenie, problem naprawiony ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1