天天看點

Gradle tip #3: Tasks ordering

I noticed that the quite often problem I face when I work with Gradle - is tasks ordering (either existing or my custom ones). Apparently my build works better when my tasks are executed at the right moment of the build process :)

我注意到我在使用Gradle的時候遇到的大多數問題都是和task的執行順序有關的。很明顯如果我的建構會工作的更好如果我的task都是在正确的時候執行。

So let's dig deeper into how can we change tasks execution order.

下面我們就深入了解一下如何更改task的執行順序。

I believe the most obvious way of telling your task to execute after some other task - is to use <code>dependsOn</code> method.

我認為最直接的方式來說明的你task的執行時依賴别的task的方法就是使用dependsOn方法。 

Let's consider existing task <code>A</code> and we need to add task <code>B</code>which executes only after task <code>A</code> is executed:

比如下面的場景,已經存在task A,我們要添加一個task B,它的執行必須要在A執行完之後: 

Gradle tip #3: Tasks ordering

This is probably the easiest thing you can do. Given that tasks <code>A</code>and <code>B</code> are already defined:

這是一個很簡單的場景,假定A和B的定義如下:

What you need to do - is just tell Gradle that task <code>B</code> depends on task <code>A</code>

隻需要簡單的調用B.dependsOn A,就可以了。 

This means that whenever I try to execute task <code>B</code> - Gradle will take care of executing task <code>A</code> as well:

這意味着,隻要我執行task B,task A都會先執行。

Alternatively, you could declare such a dependency right inside task configuration section:

另外,你也可以在task的配置區中來聲明它的依賴:

Result is the same.

But what if we want to insert our task inside already existing task graph?

如果我們想要在已經存在的task依賴中插入我們的task該怎麼做呢? 

Gradle tip #3: Tasks ordering

The process is pretty much the same:

過程和剛才類似。

original task graph:

our new custom task:

output:

Please note, that dependsOn adds task to the set of dependencies. Thus it is totally fine to be dependent on multiple tasks:

注意dependsOn把task添加到依賴的集合中,是以依賴多個task是沒有問題的

Gradle tip #3: Tasks ordering

Now imagine that our task depends on 2 other tasks. For this example I decided to use more real-life case. Imagine I have one task for unit tests and another for UI tests. Also I have a task which executes both unit &amp; UI tests:

現在假定我又一個task,它依賴于其他兩個task。這裡我使用一個真實的場景,我有兩個task,一個單元測試的task,一個是UI測試的task。另外還有一個task是跑所有的測試的,它依賴于前面的兩個task。

Gradle tip #3: Tasks ordering

Even though tasks <code>unit</code> and <code>UI</code> tests will be executed beforetask <code>tests</code>, the order of execution for tasks <code>ui</code> and <code>unit</code> is not determined. Right now I believe they will be executed in alphabetical order, but this behavior is an implementation detail and you definitely should not rely on this fact.

盡管unitest和UI test會子啊test task之前執行,但是unit和ui這兩個task的執行順序是不能保證的。雖然現在來看是按照字母表的順序執行,但這是依賴于Gradle的實作的,你的代碼中絕對不能依賴這種順序

Since UI tests are executing much longer than unit tests, I want my unit tests run first and only if everything OK - proceed to executing UI tests. So what should I do if I want my unit tests run before UI tests?

由于UI測試時間遠比unit test時間長,是以我希望unit test先執行。

One way for solving this would be to make UI test task depend on unit test task:

一個解決辦法就是讓ui task依賴于unit task:

Gradle tip #3: Tasks ordering

output

Now my unit tests are getting executed before UI tests! Great!

現在unit test會在ui test之前執行了。 

BUT! There is one really big fat nasty problem with this approach! My UI tests do not really depend on unit tests. I wanna be able to run my UI tests separately, but now every time I want to run my UI tests - my unit tests will be run as well!

但是這裡有個很惡心的問題,我的ui測試其實并不依賴于unit test。我希望能夠單獨的執行ui test,但是這裡每次我執行ui test,都會先執行unit test。 

That's where <code>mustRunAfter</code> method comes into play. It tells Gradle to run task after task specified as an argument. So essentially, we do not introduce dependency between our unit tests and UI tests, but instead we told Gradle to give unit tests priority if they are executed together, so unit tests are executedbefore our UI test suite:

這裡就要用到mustRunAfter了。mustRunAfter并不會添加依賴,它隻是告訴Gradle執行的優先級如果兩個task同時存在。比如我們這裡就可以指定ui.mustRunAfter unit,這樣如果ui task和unit task同時存在,Gradle會先執行unit test,而如果隻執行gradle ui,并不會去執行unit task。

And the dependency graph looks like: 

依賴關系如下圖: 

Gradle tip #3: Tasks ordering

Notice that we lost explicit dependency between UI tests and unit tests! Now if I decide to run just UI tests - my unit tests won't be executed.

Please note that <code>mustRunAfter</code> is marked as "incubating" (as of Gradle 2.4) which means that this is an experimental feature and its behavior can be changed in future releases.(mustRunAfter在Gradle2.4中目前還是實驗性的功能。)

Now I have task which runs both UI and unit tests. Great! Let's say each of them produces test report. So I decided to create a task which merges 2 test reports into one:

現在我們已經有兩個task,unit和ui,假定這兩個task都會輸出測試報告,現在我想把這兩個測試報告合并成一個: 

Gradle tip #3: Tasks ordering

Now if I want to get test report with both UI &amp; unit tests - I execute <code>mergeReports</code> task:

現在如果我想獲得ui和unit的測試報告,執行task mergeReports就可以了。

It works, but... it looks sloppy.. <code>mergeReports</code> task doesn't make a lot of sense from user (by user I mean developer :) ) perspective. I want to be able to execute <code>tests</code> and get merged report. Obviously, I could add merge logic inside <code>tests</code>task, but for the sake of this demo - I want to keep this logic in separate <code>mergeReports</code> task.

這個task是能工作,但是看起來好笨啊。mergeReports從使用者的角度來看感覺不是特别好。我希望執行tests task就可以獲得測試報告,而不必知道mergeReports的存在。當然我可以把merge的邏輯挪到tests task中,但我不想把tests task搞的太臃腫,我還是繼續把merge的邏輯放在mergeReports task中。 

finalizedBy method come to the rescue. Its name is quite self-explanatory - it adds finalizer task to this task.

finalizeBy來救場了。顧名思義,finalizeBy就是在task執行完之後要執行的task。

So let's modify our script as follows:

修改我們的腳本如下:

Now I'm able to execute <code>tests</code> task and I still get my merged test report:

現在執行tests task就可以拿到測試報告了:

Please note that <code>finalizedBy</code> is marked as "incubating" (as of Gradle 2.4) which means that this is an experimental feature and its behavior can be changed in future releases.(注意,finalizedBy也是Gradle2.4的實驗性功能)

This is pretty much it - with these 3 tools you can easily tune your build process!

Happy gradling!

本文轉自我愛物聯網部落格園部落格,原文連結:http://www.cnblogs.com/yydcdut/p/4821611.html如需轉載請自行聯系原作者

繼續閱讀