JakartaEE項目的現代化測試實踐

因佛科技 2024-05-25 09:45:26

作者 | Otavio Santana

譯者 | 王強

策劃 | Tina

在動態的軟件開發世界中,開源項目的重要性怎麽強調也不爲過。這些協作成果推動了創新,並爲技術領域的質量和持續性建立了基准。很多長期項目,例如已開源發布二十多年的 Java,還有 Jakarta EE 規範及其實現,都體現了開源計劃的影響。

這些項目提供了很多寶貴的見解和方法,可以很容易地應用于各種企業環境,充分體現了強大的文檔和測試文化的重要性。

本文旨在深入探討一些最新規範中所采用的一系列測試程序和工具,重點關注數據驅動的測試方法。通過研究這些方法,我們試圖找出確保開源項目質量、可靠性和長壽的秘訣。我們將探索不斷發展的軟件開發領域中測試實踐的複雜性,並探究如何利用這些原則來提高企業項目的質量。

我們將專注于目前正在發展的兩個最新規範:Jakarta Data 和 Jakarta NoSQL。這些新興規範代表了 Jakarta EE 生態系統中的創新工作,並有望重新定義 Java 企業級應用程序與數據的交互方式。

Jakarta Data 是 Jakarta EE 家族的最新成員之一,它定義了一組核心 API,旨在幫助開發人員構建 Jakarta EE 應用程序,並輕松訪問各種數據技術。

此規範使開發人員能夠利用關系和非關系數據庫、基于雲的數據服務和其他數據技術的優勢。 其目標是在 Jakarta EE 應用程序中培養一種更靈活、適應性更強的數據管理方法。

@Repository 注釋是 Jakarta Data 的重要組成部分,因爲它提供了存儲庫接口。 此接口在你的域和數據庫之間提供了簡單的連接,允許你以域爲中心的方式訪問多個數據庫。

圖 1:Jakarta Data 表示

同樣,Jakarta NoSQL 代表了 Jakarta EE 演進的又一步。此規範和 Jakarta Data 爲開發人員提供了一種將 Java 應用程序與 NoSQL 數據庫集成的標准化方法。

我們的研究將圍繞這兩個規範及其實現,主要通過 Eclipse JNoSQL 的視角來展開。我們的目標是揭示它們如何爲 Jakarta EE 項目中以數據爲中心的測試方法鋪平道路。通過探索數據驅動的測試原則,我們將深入解析那些確保 Jakarta EE 項目的質量、可靠性和壽命的複雜性。通過關注 Jakarta EE 的最新進展及其對測試方法的潛在影響,我們努力爲開發人員和企業提供在不斷發展的軟件開發領域持續進步所需的知識和工具。

圖 2:Eclipse JNoSQL 插圖,說明了使用這兩個規範,我們可以在 NoSQL 數據庫之間切換

現在,我們已經爲全面探索 Jakarta Data 和 Jakarta NoSQL 規範做好了准備,我們將深入研究這些規範如何改進 Jakarta EE 項目中的測試方法。我們將重點介紹作爲我們實現平台的 Eclipse JNoSQL 。在下一節中,我們將開始一段對測試實踐進行現代化的旅程,介紹應用于 Jakarta Data 和 Jakarta NoSQL 項目的具體步驟。

測試方法

在本節中,我們將探討增強 Jakarta EE 項目中測試方法的六個基本步驟,它們用來確保整個開發過程中的穩健性和可靠性。這些步驟旨在使 Jakarta Data 和 Jakarta NoSQL 項目與當代軟件工程的需求保持一致:

測試指南:通過文檔建立清晰全面的測試程序,指導項目貢獻者采用統一的測試方法。現代測試庫:采用 JUnit Jupiter 和 AssertJ 等高級庫來簡化測試流程、增強代碼可讀性並提高整體測試效率。數據驅動方法:采用數據驅動方法進行測試,探索各種數據集以發現 Jakarta EE 項目中的潛在問題和極端情況。豐富的斷言:利用各種斷言庫全面驗證代碼行爲,確保 Jakarta EE 應用程序符合嚴格的質量標准。擴展覆蓋範圍:使用 PITest、JaCoCo 或 Cobertura 等工具擴大測試覆蓋範圍。這將使 Jakarta EE 項目開發人員能夠評估其測試的有效性並找出需要改進的領域。用于測試的容器:利用容器創建和管理隔離的測試環境,確保 Jakarta EE 應用程序的測試條件是一致且可重複的。

采用這六個步驟後,開發人員可以改進他們在 Jakarta EE 項目中的測試實踐,確保他們的應用程序在不斷變化的軟件需求面前保持穩健性、可靠性和彈性。

下面讓我們深入研究每個步驟,並揭示它們如何幫助 Jakarta EE 項目取得成功。

圖 3:在 Jakarta EE 項目中增強測試方法的步驟

在測試的第一步中,起點是文檔:它是充當羅盤的一份測試指南,引導所有項目貢獻者朝著質量和可靠性的共同願景前進。它封裝了一組最佳實踐和方法,用于管理測試程序來確保整個項目的一致性和有效性。

在 Jakarta JNoSQL 和 Jakarta Data 項目中,這些測試指南塑造了項目的測試文化,並構建了對質量的承諾。它們的內容包括:

要使用的工具:定義的測試集和相關工具,以簡化測試流程並確保貢獻之間的一致性。命名約定:測試類、方法、描述和結構的命名約定一致性可增強測試的可讀性和可維護性。具體的測試創建方法:測試創建方法指南(例如軟斷言和擴展斷言)可確保對代碼行爲的驗證。擴展覆蓋範圍:強調擴展測試覆蓋範圍,包括突變測試等技術、發現隱藏的錯誤和提高整體代碼質量。

這些指南可作爲測試的路線圖,並強調了文檔的重要性。它們爲項目貢獻者提供了明確的起點,便于無縫集成到測試框架中。例如,Jakarta Data 中的文檔(如本文提供的 Asciidoc 格式的示例所示)概述了要使用的框架、命名約定、測試結構等,以設定項目內測試實踐的標准。

要進一步探索,請參閱 GitHub 上 Jakarta Data 項目的測試指南。

作爲對該指南的補充,我們提供了以下技巧:

使用工具:推薦的工具包括 JUnit 5 與 AssertJ 的結合,提供具有增強斷言功能的測試框架。命名約定:測試類應以測試主題​命名,後跟“Test”後綴,以提升測試套件內的清晰度和組織性。測試方法描述:測試方法應使用結構化方法描述測試意圖:前綴“should”Action 名稱爲快樂路徑提供可選預期結果,爲負面場景(極端情況)提供強制性結果

例如,下面的代碼片段演示了如何使用指南創建測試:

class CalculatorTest { @Test @DisplayName("Should sum up correctly two numbers") void sumUpCorrectly() { // AAA pattern (arrange, act, assert) }}

複制代碼

首選軟斷言:建議使用軟斷言,而不是硬斷言。它們允許在單個測試方法中執行多個語句,而不會在第一次失敗時中止測試執行。這樣可以對測試場景進行更全面的驗證。

assertSoftly(softly->{softly.assertThat(pageable.size()).isEqualTo(20);softly.assertThat(pageable.page()).isEqualTo(1L);softly.assertThat(pageable.mode()).isEqualTo(Pageable.Mode.CURSOR_NEXT);softly.assertThat(pageable.cursor().size()).isEqualTo(3);softly.assertThat(pageable.cursor().getKeysetElement(0)).isEqualTo("First");softly.assertThat(pageable.cursor().getKeysetElement(1)).isEqualTo(2L);softly.assertThat(pageable.cursor().getKeysetElement(2)).isEqualTo(3);});

複制代碼

對 Jakarta EE 項目中的測試方法進行現代化的第二步,主要是精心選擇和采用現代化測試工具和庫。雖然 Jakarta EE 的根源可以追溯到 1999 年誕生的 Java EE 平台,但現代化工具對于在當今的軟件領域保持敏捷性和競爭力來說是至關重要的。

Jakarta NoSQL 和 Jakarta Data 是 Jakarta EE 中最年輕的規範之二,它們無縫集成了一些現代測試庫,以增強代碼的可維護性、可讀性和測試覆蓋率。在這些庫中,JUnit 5 的采用非常亮眼,它提供了可顯著改善測試實踐的一些高級特性。

事實證明,遷移到 JUnit 5(特別是 JUnit Jupiter)是值得的,它爲 Jakarta EE 項目帶來了許多有價值的特性。這些特性包括帶來更清晰測試意圖的測試描述、用于處理特定于環境的測試場景的環境條件,以及用于數據驅動測試的各種來源,例如值來源、方法來源和參數來源。

通過利用 JUnit 5 的上述特性,開發人員可以改進 Jakarta EE 項目的測試實踐,以確保在不斷變化的軟件需求面前保持穩健性、可靠性和適應性。我們來深入研究如何利用這些特性來增強 Jakarta EE 項目中的測試。

對 Jakarta EE 項目中的測試方法進行現代化的第三步是采用數據驅動測試。本質上,這種方法是使用不同的數據集叠代相同的測試代碼,從而提供一種快速增強代碼覆蓋率和可維護性的機制。

JUnit Jupiter 是 Jakarta EE 項目中的強大夥伴,主要用在 Jakarta Data 和 Jakarta NoSQL 中;它提供了 @ParameterizedTest 注釋來簡化數據驅動測試。此注釋和多種來源選項簡化了將動態數據注入測試用例的過程。

在 ValueWriterDecoratorTest 的第一個示例代碼片段中,@ValueSource 注釋用于將參數中的值注入測試方法。它能輕松測試不同類之間的兼容性。

@ParameterizedTest(name = "must be compatible to {0}")@DisplayName("Should be able to verify the test compatibility")@ValueSource(classes = {Enum.class, Optional.class, Temporal.class})@SuppressWarnings("unchecked")void shouldVerifyCompatibility(Class<?> supportedClass) { assertThat(valueWriter.test(supportedClass)).isTrue();}

複制代碼

如圖 4 所示,我們可以看到單個測試基于 @ValueSource 和不同值執行了多次。

圖 4:測試應用程序執行 ValueWriterDecoratorTest 類中定義的 shouldVerifyCompatibility() 方法

此外,JUnit Jupiter 提供了更多高級選項來動態注入參數,如 TemporalWriterTest 中所示。此處,@MethodSource 注釋從一個方法處請求值,從而使用各種輸入來測試 temporal 轉換。

@ParameterizedTest(name = "must convert {0}")@DisplayName("Should be able to convert temporal")@MethodSource("temporalDataForConversion")void shouldConvert(Temporal temporal) { String result = valueWriter.write(temporal); assertThat(result).isEqualTo(temporal.toString());}static Stream<Arguments> temporalDataForConversion() { return Stream.of( arguments(LocalDateTime.now()), arguments(LocalDate.now()), arguments(LocalTime.now()), arguments(Year.now()), arguments(YearMonth.now()), arguments(ZonedDateTime.now()) );}

複制代碼

JUnit Jupiter 的優點在于其靈活性,允許開發人員將測試與特定數據值分離。它能夠與外部數據源(如 Data Faker、數據庫或 Web 服務)無縫集成,而不會影響測試套件的完整性。通過利用 JUnit Jupiter 提供的數據驅動測試方法,Jakarta EE 項目可以實現更高的測試覆蓋率和可維護性,同時確保其軟件解決方案的穩健性和可靠性。

在對 Jakarta EE 項目中的測試方法進行現代化的過程中,第四步是利用 AssertJ 等庫提供的大量斷言。這些庫通過許多斷言和特性豐富了測試工具包,包括用于簡化和增強驗證過程的軟斷言方法。

AssertJ 以其自帶的一個流暢的 API 庫而聞名,它擴展了可用斷言的範圍並顯著提高了代碼的可讀性。這種增強的可讀性在 KeyValueQueryParserTest 等測試中得到了體現,其中 AssertJ 的流暢 API 簡化了驗證過程。

@Test@DisplayName("Should execute prepared statement using 'put' setting a value")void shouldExecutePrepareStatement2() { // code ignored assertSoftly(softly -> { softly.assertThat(entity.key()).as("key is equal").isEqualTo("Diana"); softly.assertThat(entity.value()).as("entity is equal").isEqualTo("Hunt"); softly.assertThat(duration).as("duration is equal").isEqualTo(ofSeconds(10L)); });}

複制代碼

在此示例中,AssertJ 軟斷言方法中的 assertSoftly() 方法允許在單個測試方法中執行多個斷言,而不會在遇到第一次失敗時中止測試執行。它帶來了對測試場景的更全面驗證,同時保持了測試代碼的可讀性和清晰度。

通過采用 AssertJ 等庫提供的大量斷言,Jakarta EE 項目可以增強其測試套件的穩健性、可靠性和可維護性,最終確保其軟件解決方案的質量和完整性。

對 Jakarta EE 項目中的測試方法進行現代化的第五步,我們轉向突變測試。這種先進的技術使我們能夠發現隱藏的錯誤並評估測試的強度。

PITest 是一種爲 Java 和 JVM 設計的最先進的突變測試系統,在此過程中發揮著關鍵作用。PiTest 自動將故障或突變引入我們的代碼庫,使我們能夠評估我們的測試對這些變化的響應程度。

突變測試的工作機制如下:將故障注入代碼,然後執行我們的測試。如果測試失敗,表明它檢測到了突變,則認爲突變已被終止。相反,如果測試通過,意味著它未能檢測到突變,則突變仍可存活。

在 Eclipse JNoSQL 項目中,我們可以使用一個簡單的命令將 PiTest 無縫集成到我們的測試工作流程中:

mvn clean test-compile -P pitest

複制代碼

此命令觸發分析過程,生成全面的報告,提供有關測試覆蓋率、變異分數和測試強度的見解。這些報告可通過位于 target/pit-reports 的 文件訪問。

圖 5:針對 Eclipse JNoSQL 通信核心項目的 PITest 執行

上圖 5 顯示了 PiTest 的實際運行情況,展示了覆蓋率、變異和測試強度指標。這種直觀的表示使我們能夠評估測試的有效性並找出改進領域。

通過 PITest 和突變測試,Jakarta EE 項目可以擴展其測試覆蓋範圍,檢測潛在錯誤,並提高其軟件解決方案的整體質量和可靠性。借助 PITest,我們可以確保我們的測試穩健而全面,從而對我們應用程序的穩定性充滿信心。

對于 Jakarta Data 和 Jakarta NoSQL 項目,改進測試方法的最後一步是利用容器進行測試。由于核心數據庫的集成情況,這一步至關重要,因爲確保無縫交互和兼容性是必要的。

對 Jakarta EE 項目中的測試方法進行現代化的第六步也是最後一步中,Testcontainers 會用作一個強大的測試庫。Testcontainers 提供簡單輕量級的 API,通過封裝在 Docker 容器中的精確服務簡化了集成測試的引導工作。其功能可以管理測試期間數據庫的生命周期,以保證測試開始時的初始化、執行期間的持久性和之後的正確拆卸。

在 JNoSQL-Database 項目中,多個集成需要與數據庫直接集成,因此測試對合約的確認是非常重要的。在這裏,我們見證了 Testcontainers 的實際操作,它無縫地協調數據庫容器的設置和拆卸,以促進全面測試。

爲了優化資源使用,該項目盡可能采用單例模式實例,盡可能減少初始化數據庫實例的開銷。這裏使用了兩種主要樣式:管理容器的單例模式和基本測試模式。該項目正在向源自 Testcontainers 文檔的標准化結構過渡,以確保測試管理的一致性和清晰度。

abstract AbstractContainerBaseTest { static final MySQLContainer MY_SQL_CONTAINER; static { MY_SQL_CONTAINER = new MySQLContainer(); MY_SQL_CONTAINER.start(); }}class FirstTest extends AbstractContainerBaseTest { @Test void someTestMethod() { String url = MY_SQL_CONTAINER.getJdbcUrl(); // Create a connection and run test as normal }}

複制代碼

爲了提高測試執行的靈活性,開發人員利用多個屬性,根據系統屬性有選擇地啓用或禁用集成測試。可以根據需要切換重量級集成測試。

@EnabledIfSystemProperty(named = "jnosql.test.integration", matches = "true")class MongoDBDocumentManagerTest { // Executes test with a container}

複制代碼

這種方法使開發人員能夠有效地管理測試執行,有選擇地運行資源密集型測試,從而優化 Jakarta EE 項目中的測試流程。通過利用容器進行測試,Jakarta Data 和 Jakarta NoSQL 項目可以驗證數據庫集成,從而提高其軟件解決方案的可靠性和穩健性。

利用容器在 Jakarta EE 項目,特別是在 Jakarta Data 和 Jakarta NoSQL 項目中進行測試,對于確保軟件解決方案的穩健性和可靠性至關重要。Testcontainers 具有輕量級 API 和無縫 Docker 容器集成,有助于全面測試數據庫交互。將 Testcontainers 與已建立的測試模式和實踐(例如 Singleton 實例和靈活的測試執行切換)並用後,Jakarta EE 開發人員可以簡化測試流程並驗證數據庫集成。這種細致的方法不僅提高了軟件解決方案的質量和可靠性,還使開發人員能夠自信地應對 Jakarta EE 生態系統中數據庫集成的複雜性。

總結

下面總結我們對 Jakarta EE 項目中測試方法進行現代化的探索結果,很明顯,提高代碼質量和可靠性是一項持續不斷的努力。采用一系列創新工具和實踐,例如數據驅動測試、廣泛的斷言和基于容器的測試,標志著行業在確保軟件解決方案的穩健性方面取得了重大進展。

重要的是要認識到,與任何開源計劃一樣,Jakarta Data 和 Jakarta NoSQL 項目仍然充滿活力並不斷尋求改進。貢獻者、測試人員和用戶的積極參與對于推動這些項目向前發展、改進測試方法和提高 Jakarta EE 應用程序的可靠性是非常關鍵的。

對于那些尋求軟件測試進一步見解和指導的人們來說,有很多參考資料和資源可用。一個值得推薦的是 Maurizio Aniche 的《有效軟件測試:開發人員指南》,這是一本內容全面的著作,改變了許多人的測試實踐。

此外,著名質量工程師和 Java Champion Elias Nogueira 等人的指導和領導在促進 Jakarta EE 項目中的良好測試實踐方面發揮著關鍵作用。 Nogueira 的博客和在 Twitter 等社交媒體平台上的活躍表現,爲尋求提升對測試的理解並爲推進 Jakarta EE 項目做出貢獻的開發人員提供了寶貴的資源。

在我們探索不斷發展的軟件開發領域時,讓我們繼續致力于在 Jakarta EE 項目中培育質量、協作和持續改進的文化。我們可以共同賦能開發人員,加強測試實踐,並提供無與倫比的可靠性和卓越性軟件解決方案。

作者介紹:

Otavio 是一位屢獲殊榮的軟件工程師和架構師,他熱衷于爲其他工程師提供開源最佳實踐,以構建高度可擴展且高效的軟件。他是 Java 和開源生態系統的知名貢獻者,並因其工作獲得了無數獎項和榮譽。Otavio 的興趣包括曆史、經濟、旅行,並且精通多種語言,還非常幽默。

原文鏈接:https://www.infoq.cn/article/F1lgF4zUwpHgNWsakFCq

0 阅读:1

因佛科技

簡介:感謝大家的關注