2016-11-15 12 views
6

Ostatnio dużo o tym myślałem i chciałem uzyskać kilka opinii na temat tego, co miałem kilka dni temu.Opinie na temat konfiguracji gradle dla `test-support` kod

Problem:

W typowej bazie kodu, każdy moduł posiada i test źródłowego zbioru main. To może działać całkiem dobrze przez pewien czas, ale wcześniej czy później zawsze natknę się na sytuację, w której chciałbym zgrupować kilka klas, które pozwalają na łatwiejsze testowanie kodu, który wymaga określonego modułu. Dobrym przykładem może być zestaw klas matchera hamcrest dla danego modułu.

  • Założenie 1:
    Jak hamcrest jest biblioteką dla badanego kodu, te dopasowujące nie powinien iść do źródłowego zbioru main.

  • Założenie 2: Klasy te nie powinny również przejść do test źródło ustawione albo, jak zależność od źródła test to tylko obejście te zajęcia mają być dostępne. Zazwyczaj nie zależy od rzeczywistych testów. Jest również not recommended (przez Netflix), aby zdefiniować zależność od zestawu źródłowego projektu test.

Rozwiązanie 1:

Tworzenie dedykowany moduł, który zawiera te zajęcia w main źródło ustawiony i po prostu zdefiniować test-zależność od tego modułu wszędzie tam, gdzie są potrzebne.

To było podejście, z którym miałem do czynienia od jakiegoś czasu, ale nie bardzo to lubię.

  • Po pierwsze, nigdy nie wpadł ładne imię, z wyjątkiem dopisywania testSupport do nazwy oryginalnego modułu, co skutkuje nazwami jak core-testSupport, persistence-testSupport i tak dalej.

  • Po drugie, tworzy wiele modułów, a drzewo projektu jest zanieczyszczone tymi modułami.

Rozwiązanie 2 (Ten Byłbym wdzięczny za opinię na temat)

configurations { 
    testSupportCompile.extendsFrom compile 
    testSupportRuntime.extendsFrom runtime 
} 

sourceSets { 
    testSupport { 
     compileClasspath += sourceSets.main.output + configurations.testSupportCompile 
     runtimeClasspath += compileClasspath + configurations.testSupportRuntime 
    } 
} 

task testSupportJar(type: Jar) { 
    from sourceSets.testSupport.output 
    classifier 'testSupport' 
} 

artifacts { 
    testSupportCompile testSupportJar 
} 

Powyższa konfiguracja Gradle może pójść w pliku o nazwie testSupport.gradle i być stosowane do każdego modułu, który tego potrzebuje dedykowanego source- zestaw do zapewniania klas, które można ponownie wykorzystać w testach.

Definiowanie zależność będzie działać tak:

testCompile project(path: ':core', configuration: 'testSupportCompile') 

nadal jestem trochę nowy w Gradle i zbadane dużo, ale mam jeszcze kilka pytań.

  1. Rozumiem, że deklarując nowe źródło ustawione automatycznie tworzy dwie konfiguracje: <sourceSet>Compile i <sourceSet>Runtime. To, co nie podoba mi się w tym podejściu, polega na tym, że podczas deklarowania zależności należy użyć konfiguracji TestSupport Compile. Czy istnieje sposób na alias to tylko do testSupport lub coś w tym stylu?

  2. Mój projekt świetnie się teraz kompiluje. Jednak nie jestem pewien, czy robię rzeczy we właściwy sposób. Jak można poprawić tę konfigurację?

  3. Czy istnieją inne sposoby osiągnięcia pożądanej funkcjonalności? Podczas badań nie znalazłem zbyt wiele na ten temat, dzięki czemu mam wrażenie, że albo używam złych terminów wyszukiwania, albo robię coś głupiego, czego po prostu nie powinno się robić.

Wiem, że to jest szerokie pytanie, ale nie jestem pewien, gdzie uzyskać odpowiednie opinie na temat takich rzeczy, z wyjątkiem tutaj.

Odpowiedz

1

Mam podobną sytuację i odkładam rozwiązanie na jakiś czas, używając różnych hacków i work-aroundów. Twoje pytanie było ostatecznym bodźcem, aby to sprawdzić.

To, co skończyło się - EDIT wykonany we współpracy z Thomas:

configurations { 
    // create a new configuration and inherit everything from compile 
    testlib.extendsFrom compile 
} 

sourceSets { 
    testlib { 
     // We will at least need access to our main sourceSet and all dependencies that are declared for our configuration. 
     compileClasspath += sourceSets.main.output + configurations.testlib 
    } 
} 

task testlibJar(type: Jar) { 
    from sourceSets.testlib.output 
    classifier 'testlib' 
} 

artifacts { 
    testlib testlibJar // include the classes into the new configuration 
    archives testlibJar // optional: include the support JAR into "uploadArchives", so it may also be used in other projects 
} 

Następnie, w zależności od modułu, wystarczy użyć:

dependencies { 
    testCompile project(path: ':otherproject', configuration: 'testlib') 
} 

Należy pamiętać, że (puste) testlibCompile i testlibRuntime konfiguracje są nadal tworzone (w wyniku wprowadzenia nowego zestawu źródeł), ale uważam, że można bezpiecznie je zignorować.

Często zdarza się również, że konfiguracja własna projektu test wymaga użycia testlib (testy projektu zależą od ogólnego wsparcia testowego). W takim przypadku, można dodać do niej zależność pomiędzy dwiema konfiguracjami tego samego projektu:

testCompile project(path: ':myproject', configuration: 'testlib') 

Albo zwiększyć kompilacji i czasu wykonywania zmiennymi CLASSPATH indywidualnie:

configurations { 
    testlib.extendsFrom compile 
    testCompile.extendsFrom testlib 
} 
sourceSets { 
    test { 
     compileClasspath += sourceSets.testlib.output 
     runtimeClasspath += sourceSets.testlib.output 
    } 
} 
+0

Gdybym interpretować swoje rozwiązanie poprawnie, tylko różnicą jest zależność impliksu testLib od testu (co wydaje się być w porządku). Zajrzę do tego tak szybko, jak będę w domu. –

+0

Główna różnica polega na użyciu konfiguracji 'testSupport' zamiast' testSupportCompile' zarówno w sekcji 'konfiguracje' i' archiwa'. – Marwin

+0

Myślę, że miałem to również jako rozwiązanie pośredniczące, ale bez ukrytej zależności od konfiguracji 'test' w konfiguracji' testSupport'. Problem polega na tym, że bez tej niejawnej zależności musiałbyś zadeklarować ją jawnie w każdym module, który nie zadziała, jeśli nie użyjesz ponownie konfiguracji, które są automatycznie tworzone przez zestaw źródłowy. Btw: Nie musisz wyraźnie ustawiać srcDir zestawu źródłowego. Plik srcDir z nazwą konfiguracji jest tworzony niejawnie. –

Powiązane problemy