搜尋

搜尋結果

你開始寫 Spring Boot 測試案例了嗎?
科技新知
MacauYeah・2025-11-29

雖然筆者過往做 spring boot framework 教學中,都有滲入一些測試用例。筆者也曾經困惑了很長一段時間,所以就獨立開一個主題,聊一下筆者在實務上對spring boot test 的理解。 測試案例究竟測試什麼? 測試用例 test case 是確保你的程式碼正確性與穩定性的重要步驟,但在 framework 下,並不是所有功能都很容易寫成測試。所以在討論 framework 測試之前,釐清測試的本質。 function input business logic function output 這意味著我們輸入某些資料(input),然後經過業務邏輯(business logic)的處理,最後產生結果輸出(output)。 我們的測試目標,其實就是確保業務邏輯正確。而我們的手段就是經檢查概定的輸入資料,核對輸出結果。 那麼只要我們可以生成輸入資料,就一定可以檢查輸出結果了吧?其實不是的,因為實務上的輸入和輸出沒有這麼簡單。筆者常接觸到的輸入輸出如下 輸入 function 輸入參數 系統狀態資料,例如:資料庫狀態、外部API結果。 輸出 function 輸出參數 寫入系統(影響到)的資料,例如:資料庫狀態、使用外部API時的輸入參數。 總之就是考慮了狀態機 state machine 的問題,每個狀態外部輸入都是一個測試用例,然後核對狀態機去了下一個什麼狀態。 言下之意,我們就是暴力地生成輸入參數和模擬狀態資料,道理上就是可以進行測試。 Spring boot web framework 中,我們又會測試什麼? function input business logic function output在Spring boot web就變成如下 controller request business logic controller response在 Spring Boot test 中,我們可以用模擬的 MVC MockMvc 測試來驗證 controller 的行為。不過,其實進入 controller 前經過很多系統轉換,而這些道理上跟Framework的技術大相關,與業務邏輯小相關。所以為免折磨自己,可以將業務邏輯單獨封裝成服務(service)。之後直接測試服務 ,易寫也易讀。 controller request service input business logic service output controller response道理上 controller 能做的業務邏輯,服務 service 都可以無腦重現。這樣還可以重用服務,減少測試的數量。 如何實現輸入? 直接 new Object。大部份的情況下,因為業務是自己編寫的,應該都可以直接 new 出來。 經 json 檔讀入。如果輸入的參數量太多,逐個經 java new 是很耗時的,我們可以經 json 反序列化變成 Object。但這亦只限於自己可以操作改寫的類。 Mockito 模擬那些無法簡易經 new 或 json 反序列化的 Object。例如:spring security authentication object 我們在使用時,其實只看到 interface。我們難似自己實現一個可以反序列化的類,那麼我們可以使用 Mockito 來模擬這些資料。一些外部API的結果,我們也可以用使 Mockito 來模擬。 什麼情況下不進行測試? 有些情況下,我們可能選擇不對某些功能進行測試,原因可能包括對功能的了解不足或是單純的懶惰。以下是一些例子: 僅進行配置的Function:如果你的 Function 只是在 Framework 中填寫配置,而且你並不太了解它的運作原理,可能就不需要進行測試了。例如,Spring boot web 中,需要大家配置一個SecurityFilterChain Object,它要求大家將 HttpSecurity 轉換為 SecurityFilterChain 。因為輸入的 HttpSecurity 是系統固定的參數,我們亦沒有檢查它的狀態。這種情況下,它的輸入及輸出,其實我們都沒有真正理解。我們硬測試的話,測試功能可能只流於表面。若我們真的要做測試,也是經過MockMvc進行端到端測試(endtoend testing),測試它在事後的影響範圍。 單純的框架功能:例如資料庫的儲存庫介面(repository interface),雖然是在框架下生成的,對於自己手動調整的部份功能,筆者通常亦不會進行單獨測試,通常都會搭配業務邏輯一起進行。它可以使用 Mockito 進行模擬測試,或用測試環境的真實資料庫進行測試。 面對的挑戰 總括來講,筆者盡可能地把測試用例限定在業務邏輯中,就可以大大地降低寫測試的技術難度。但筆者還是有些問題並未完美解決。 測試用例的數量可能很多,因此共用與維護變得相當困難。逐個用例獨立編寫輸入也是很累的。對於 Mockito 的使用,筆者還是可免則免。因為要逐個功能模擬,編寫量就指數提高,這亦難似配合外部變化。一般來說,能優先使用測試環境或者 Docker 來模擬環境的,就盡量用。 離線開發、離線測試。系統依懶的外部功能越多,想做單機開發的難度就越高。即使前述有 Docker 測試,對於持續整合(CI)來講也是有一定難度。那麼這時,Mockito 就是一個可取的選擇。但這又回到編寫量及難以偵測外部變化問題。 希望這篇文章能幫助你更好地理解測試案例的編寫方向,並在Spring boot web開發中加入你自己的測試!

Docker 中的非管理員用户 Docker non-root user
科技新知
MacauYeah・2025-03-14

Container USER為何重要 在制作Docker Image的過程中,有時會接觸到 USER 這個設定。這事關到最後的 Docker Container內部運行的那個 user 到底會有什麼權限。大家也要知道,Docker Container 其實也只是一個 Linux 上的程序,也就是如果Container內權限過大,也有機會從 Container 內部存取到 Host上的資料。 一般情況下,Docker Image 預設的 USER 就是 root,最基礎的base image都是一樣。而我們想換,其實也相當簡單,就像Linux上起User一樣,只要經指令RUN adduser xxx 或RUN useradd xxx 也可以在 Docker Image 中創建帳號和 home 資料夾,之後就隨時經USER xxx來切換 實際上是不是這麼簡單 如果你將要Container中執行的程序,是一個binary,平常你在Linux中也是以 nonroot 方式執行,那麼是的,就是那麼簡單。例如你執行系統中的java, node, python,原本在Linux中就已經是誰都可以,那麼你的docker container 也應該沒有難度。 但如果原本的安裝包,預設是由system service來啟動,我們就要花點力氣,看看那個service是怎樣呼叫binary的,然後就一步一步模擬它的做法。例如筆者有打包的codeserver,預設是system service啟動,但它也有提共binary的執行方法,安定好home資料夾後,我們也可以手動啟動。 泛生之檔案權限問題 上述binary的情境之所以簡單,是因為大部份情況下,我們都只對於container 內部運行考慮即可,因為預設投產情況下的運作模式,都是隨時起、隨時刪、隨時砍掉重練,只要container內部運作可以自給自足,就可以了。Docker Swarm的運作也是如此,所以它不預期有的持久化資料權限的問題。 而持久化資料權限的問題,其實早在單個Linux伺服器就已經存在。同一個伺服器中,不同process就有不同的UID,當他們需要共同讀寫某些檔案,就會設定多人權限。同理,當多個Container要共同檔案,也是同樣問題。在討論共享檔案之前,我們先看看預設 Docker Storage Mount 會給我們什麼權限。 如果是bind mount,bind mount的權限預設會是Host內的檔案或者資料夾的權限。 如果Host是root,container內是nonroot,container有機會無法讀寫bind mount內的檔案。 留意權限設置就可以解決問題 如果Host是nonroot,但container 內是root,從container內生成的檔案,Host的nonroot user就無法使用。 Host是nonroot的話就一定無解,Host至少有sudo權限,臨時變成管理員,去修正問題。 如果host和container也是nonroot,但UID不夾,其實也不能交換使用。 跟上述一樣,最後要靠sudo來解決問題。 如果host和container也是root,就沒有權限問題,但就有安全性的風險。 如果是volume mount,就還是看看 mount path 是docker image layer中現有的 path還是新起的path 大部份手動建立的named volume都是root 經docker compose起的named volume滿足以下條件的話,將會是nonroot。 docker image 中的已有該path存在。 named volume未存在,docker compose會把對應path的內容在初次建立時抄到named volume 中。 例如ubuntu24.04中的homeubuntu,存在於docker image中,它的擁有者就是UID 1000,我們經docker compose HOME_VOLUMEhomeubuntu,在HOME_VOLUME建立時,就會是UID 1000。但如果是 NOT_EXISTShomeubuntusomethingNotExists,那麼NOT_EXISTS建立時,也會是root 上述討論的Storage mount是集中在單機情況下,使用HOST OS的本地儲存。若現在的場境是多機共享的share storage,就會更麻煩,還要看看那個share storage本身的屬性。例如常見的Linux NFS,其實有指定的權限,跟NFS的Login權限有關,如果你的process本身對檔案權限很敏感,就請先不要挑戰NFS例如postgresql。 Rootless mode Rootless 模式 Rootless 模式指的是在Host中,執行Container的使用者,不需要是管理員,筆者就常用於開發環境中。投產環境中反而沒有聽過這樣的討論,因為投產環境很少可以讓非管理員去執行這麼重要的環境管理。 雖然只是開發環境,但這像前述的bind mount討論中,如果Host是nonroot,但container 內是root,又或是兩者nonroot,但UID不夾,也會出現權限問題。無腦的將host user加入docker group,只可以讓非管理員可以運行docker,但解決不了權限問題。 真正有條件解決的,可能就會向linux subgroup的方式發展。暫時筆者用得比較順的rootless mode,可以無腦用的,不是docker,是podman。有興趣的朋友可以經podman官網看看教學,它給筆者的感覺就像是自動轉換UID。 podman rootless mode 想看更多 筆者已經將過去的文章重新整理成gitbook,有興趣睇更多的讀者,可以來筆者的gitbook再翻一翻 httpsmacauyeah.github.ioAProgrammerPrepares

發佈Docker Swarm App的選擇 - CI/CD系統的參與
科技新知
MacauYeah・2023-08-25

一段時間前,筆者就討論了一些Docker打包的程式的文章,也討論了一些Docker Cluster環境下的選擇。現在也是時候,可以分享一些對於發佈環境的可選空間。 CICD系統 CICD 全稱是continuous integration CI 和 continuous delivery CD,字面上代表的持續地集成和發佈,實體上就是某台伺服器自動發佈APP。因為使用到Docker Cluster,不論前述什麼選擇 前文連結 請點這裏,都會有多個node節點的出現。要發佈App,總不能一個個node逐個登入設定。所以我們需要一些CICD工具,把這個過程都自動化。 在筆者的認知上,CICD系統,由兩個部份組成,一個是取得Source Code程式原始碼的過程,一個是編譯或發佈Source Code的過程。Gitlab,Github,BitBucket等大型的代碼庫供應商,它們天生為了保存Source Code而提供服務的。不少CICD系統都可以跟它們整合,它們提供了存取Source Code的部份,剩下你只要能提供編譯或發佈的伺服器就好。 如果作為小型開發團隊,很少會有意願去自己花錢養一個編譯或發佈的伺服器。極端地,如果我就是一人團隊,我用自己電腦編譯和發佈就好,伺服器能做的,我自己也能做。好消息的是,Github提供了一個叫Github Action的CICD系統,即使你沒有自己的編譯專用的伺服器,Github Action也可以用Docker Image,提供一個臨時的編譯程序,用完就刪掉。詳細功能還請各位先查看官方教學,筆者也暫時只能零星使用經驗,無法給出有意思的架構。 如果對智慧財產權有高度重視,Source Code不能存放在公開的伺服器,那麼Gitlab Enterprise Edtion則是一個好選擇。運用Gitlab ee,你可以用自己的機器,造一個純本地的庫存伺服器。更強的是,它內建也有CICD系統,只要你有間置的伺服器,就可以作為編譯使用。筆者也是從這個方向著手,架設了自己的Gitlab RunnerGitlab CICD系統。在這裏,就分享一下與Docker Swarm整理的概念。 對於前述兩種選擇,GitLab Runner都可以做得到 底層程式打包成Image並運行在Swarm mode上,每次發佈的是App Binary執行檔或核心檔案。 把App直接打包成Image,並運行在Swarm mode上,每次發佈的是App Image。 CICD 打包底層程式成為Image 在這個選擇下,其實就跟傳統自動化發佈的做法類似,只是發佈時,要多個node報行更新指令。如果你使用的底層程式原本就有支援多版本並行,這樣更新時就不用太操心rollback回滾等操作。若系統不支援多版本並行,為求簡化,若遇到要rollback的情況,重跑過去舊的CICD操作也是一個做法。當然,我們也可以經過一些備份的操作,來保存被代替的程式,若在發佈過程中出問題,也可以手動重來,不過整件事就越來越複雜。 筆者發佈的基本思路是 使用docker image,編譯和打包App Binary。 使docker image做編譯的好處是,你可以比較放心地假設每次編譯時,你的編譯環境都是乾淨的。 傳送上述的結果至生產環境可以取用的地方。 跳入生產環境執行更新指令 這裏有些隱藏的管理成本,如果你生產環境中有多個node,最後那幾行指令就要多抄幾次。 CICD 打包App成為Image 在這個選擇下,對比傳統自動化發佈的做法,現在要多做一步,就是要包裝自己的Image。不過好處是docker swarm有提供監測工具,在發佈過程每個分身會逐個更新,前一個分身更新成功後才會到下一個分身更新。而且 rollback等的操作,你可以靠docker做到。即是要手動rollback,也可以透過更正docker tags來達到,所以整體上來說沒有比傳統的麻煩。 筆者發佈的基本思路是 編譯App Binary。 打包成docker image。 經docker上傳image。 跳入生產環境執行更新指令。 對比傳統自動化發佈的做法,最後的更新指令,只要執行一次就可以。當然,原本在Docker Swarm中要管理的事還是要好好管理。 CICD 備註事項 雖然CICD可以幫忙簡化更新的過程,但實際操作會比上述的例子複雜一些。因為通常對非技術型的外界用戶來說,一個Web App會包含很多不同的功能。上述的例仔,在實際情況下可能需要拆解成很多微服務來進行。所以對管理上還是有相當的挑戰。

良心遊戲推薦:《歧路旅人:大陸的霸者》
手機‧電玩
MacauYeah・2023-02-14

對於RPG劇情遊戲,筆者一直只會關注主機或PC平台,手機上的作品,真的不敢期待太多:新作品課金意圖太強、看下去不天天充錢就玩不下去;移植作品就是操作不良,沒有考慮手機的使用環境,還會遇到手機升級就不能玩的狀況。 不過最近,筆者終於真真正正玩了一款適合手機上的新作品 《歧路旅人:大陸的霸者》。筆者前陣才剛通關了Switch版上的《歧路旅人》八方旅人,然後它的手機版《歧路旅人:大陸的霸者》就剛好中文化,在港澳台上市了。筆者下載後,也就斷斷續續的玩,截至現在,遊玩總時數25,但這25小時體驗不比Switch 版差,什至劇情方面還比Switch 版好。筆者盡量以不劇透的方式,去表達手機版與Switch版的差異。 先講戰鬥系統,歧路旅人系列,都有不同武器和魔法屬性,只有累積打中弱點武器或魔法數次,才能破防,玩家正常情況下,亦可以在每回合中取得BP點數,然後再一口次大量輸出。手機版與Switch版最大的差異,Switch版可以通過改變角色的副職業來達到轉換武器、魔法,而手機版角色只有單一固定武器、魔法學習路線。Switch版,一次出戰只有4人,但因為副職業選擇多,容易配出全屬性泛用戰鬥隊伍。手機出戰角色為8人,分前後排出戰,後排正常情況下不會受傷,可以自動回復HP、SP、BP,但因為要經過抽卡取得角色,所以正常情況下都不會有全屬性隊伍。 手機版中,雖然抽卡很可恨,但筆者在不課金情況下,也順利通關主線基本內容,證明關卡設計還是合理。(筆者沒有課金,只需要使用遊戲內的獎勵系統去重複抽角色,大概抽夠50抽,就夠編一隊半泛用隊) 劇情系統:Switch 版中八個主線明線故事,每個四章節。手機版中三個主線明線故事,每個三章節,也有抽卡角色故事,也是每個三章節。不同主線之間可以自由切換,沒有指定順序。Switch 版故事比較多,也只有八個主線全數完成,才能有挑戰隱藏Boss,解釋全世界的來龍去脈(筆者沒有成功挑戰隱藏Boss,只能以訛傳訛)。手機版也有類似設計,在挑戰完三主線後,有些關聯發展,照推測應該也是有一個隱藏暗線(筆者實力有限,只能腦補推測)。 正如筆者於本文一開始所說,手機遊戲,大多沒有直正地考量手機的使用環境,而《歧路旅人:大陸的霸者》就好好地實現了這一點,這亦是筆者大力推薦這遊戲的第一個大原因。手機遊戲,主要在碎片化時間下遊玩,傳統的RPG劇情遊戲想搬到手機上,沒有自動Save的幫忙,根本玩不下去。而且這遊戲還是很忠實地呈現了跑圖機制,在跑圖的過程中,也有自動Save的幫忙,很適合筆者這種開遊戲2分鐘不夠又要走的人。而且戰鬥系統採用回合制,有足夠時間可以讓筆者重組策略,同時也保留了足夠的關卡難度,讓筆者感受到緊張刺激的決策效果。同時,跑圖、戰鬥選擇等操作,也有考慮好手機的方式,通關滑動去做自動化和強化。 第二個推薦這遊戲的大原因,就是遊戲中【名聲】主線的劇情,這主線絕不是普普通通的王道或復仇路線,rdquo;劇情反轉rdquo;已不能用來形容筆者所感到的震撼。大家即便不玩,也可以去各大影視平台看看錄播劇情。其他主線就顯得不太突出,但看看也無妨,因為以近年Square Enix的實力,能好好地講完一個故事,已經很不錯。這遊戲的大局觀沒有開得很大,不會像FF系列那種強行推劇情,不用怕看到一半悶到死、看完會後悔的感覺。 總括來說,如果你想在手機平台玩玩輕鬆的單人遊戲,《歧路旅人:大陸的霸者》是必玩的選擇。主線不用刷等級也能過關,遊戲操作也很切合手機平台,即使在碎片化時間下還能遊玩。 手機遊戲中文版 官方網頁 httpswww.boltrend.comzhtwot

瑰麗寶綠 ※ 茫崖翡翠湖 ※
旅遊情報
莫雪・2023-07-14

瑰麗寶綠 sect; 茫崖翡翠湖 sect; 一個宛如瑰麗寶玉翠綠的一大片人工鹽湖 茫崖翡翠湖位於青海省海西州茫崖市尕斯湖東部邊緣, 花土溝鎮西南側,距鎮政府所在地約23公里,有崑崙山南依, 阿爾金山北靠,像是一片心靈鷄湯般呈現你眼前, 醉綠而美麗的一個鹽湖。 茫崖翡翠湖鹽湖裡的鹽, 多到舖在路面上, 讓你腳踏其中, 而道路兩旁, 隨時躺著一件、二件大大小小形狀不一 的雪白結晶鹽塊石頭, 令你愛不釋手。 其實翡翠湖過去是含鉮豐富的天然鹽湖, 己然停止開發, 留作旅遊價值利用極高之風景名勝上。 上午時間來欣賞拍攝茫崖翡翠湖是最佳時機, 因陽光照射在湖面上顏色更為漂亮, 一片片鹽湖透現翡翠綠色如一塊塊寶玉, 大小不一雪白鹽結晶鑲嵌綠玉羊脂般, 剎是好看。 而深淺不一的鹽池水中的高濃度鹽水,是歷經多年的 鹽湖開採而形成的采坑, 由於所含礦物質濃度不同, 形成了顏色多彩的景象,沒風鹽水平靜時,宛若鏡面般散佈, 顏色純美剔透,淡青、翠綠、深綠的湖水如同鑲嵌在鏡面上的翠玉, 一躍而成變為一面 ldquo;天空之鏡rdquo;, 大夥更為雀躍, 紛紛留影這個最佳時刻。 這樣一塊冰清玉潔的翡翠,為茫崖這個翡翠湖增添了一份柔情若水。 注意時間別過了中午, 風起多雲時鹽水池則沒那麼透澈了。 景點相當偌大, 鹽湖總面積大約26平方公里, 門票已包括來往主要景觀吸引的幾道主要打下地方, 當漫步在長長鹽路小道之上,放眼只有閃耀著雪白天然光芒 的鹽湖與及其結晶鹽塊結構物, 而遠處,則是藍天白雲下 的一幅幅晶瑩鹽水躺漾著片片翡翠綠玉, 令人心擴神怡的獨特畫面, 再加之翡翠湖本來的寧靜,偶見遊人小群小群走過, 為這寧靜增添一點氣氛, 像是為眼前的絶色畫作添上一筆色彩。 值得親身前往欣賞, 因為茫崖翡翠湖讓你视觉震撼感更强, 相片已呈現的美未能完美表達得到, 值得你去探索。 #恩施地心洞天# #森林裡的亞列斯可湖# 其它文章, 詳情請點擊澳門科學館「蒸氣誌電子月刊」 內之「近代中國科學家事蹟及其精神」 httpswww.msc.org.mozhflipbook55STEAMISSUE 本篇文章、影片、相片版權屬作者所有,經由版權持有人授權CyberCTM.com發表。 聯絡及邀約 irene801802@hotmail.com

紅土之城 ~ 馬拉喀什
走遍世界
莫雪・2021-06-03

紅土之城 摩洛哥馬拉喀什 馬拉喀什古城裡, 有座高高矗立的清真寺紅土牌坊標誌碓樓, 遠遠便能見到。 相連的一組陶土红、黃土混合的清真寺連遺城牆建築物, 顯得風塵僕僕古磧味怏然。 那裡, 穆斯林信徒每天仍沿用的參拜禮堂, 依舊的定點禮拜召集鍾響; 一樣的呢喃禮樂聲音; 一貫的信眾崇拜者忙碌地戶外席地取水, 先潔淨手腳以示敬重; 一直延綿的宗教活動。 這座紅土碓樓的清真寺不設遊客進入參觀, 只能繞着城牆建築物走一圈, 感受一下建築物的恢宏, 配上白牆紅木圓門的設計心思, 在藍天白雲映襯下 格外嘗心悅目; 與及伊斯蘭教文化信徒對宗教堅持和信守。 清真寺對開也有片廣場, 隨意走走, 累了廣場椅子閒座, 聴聴寺內呢喃的禮頌讚聲音, 看看摩洛哥人身披長袍走過飄起舞動衣身下擺, 感覺寫意 摩洛哥的阿特拉斯的山脚下,地理處於摩洛哥南部马拉喀什,是全国第三大城市, 也是重要古都之一。 這座城市早建於公元1062年,到現在已經有一千年歷史了, 仍然保留住古老的外貌,古城放眼, 滿目皆是陶土赭红圍牆砌成、 陶土红房屋,因此, 馬拉喀什又被稱為紅城而聞名世界。 詹馬埃爾弗納廣場, 感覺是一個大大的雜耍夜市場, 遊戲動物雜耍的、講故事的人、 賣摩洛哥食品小吃與及各式飲品的人、跳舞者和音樂表演者, 讓你眼界大開, 目不睱給, 真有點像走進了古時「還珠格格」戲裡的年代, 小燕子雀躍於 那些街頭各類攤檔表演與飲食文化。白天, 相當喧嚷的廣場, 你可以頂著艷陽藍天去圍觀表演攤檔, 或是躲進仍保存完好的紅土陽台茶座喝杯咖啡, 遠觀近看一片繁忙熱鬧廣場, 感受一刻寫意時光。太陽隨隨下山, 黃昏後廣場更為熱鬧, 廣場上的食品擹點開張使得廣場變為了一個空前熱鬧的露天餐廳; 人山人海, 熙来攘往, 呈現了中世纪的繁華商市面貌 當你以為去了那一個的泰國或台北夜市場, 偶然有馬車經過, 載貨或是 招客人馬車遊覽的; 又或是身旁頭經過頭戴小白巾帽、 身穿長袍的阿拉伯人, 才把你喚回去非洲繁忙的角度裡去。 廣場方圓周圍便是濃郁的伊斯兰教風格大街小巷,伊斯兰教的建築和商店舉目皆是, 商品見過沒見過的都令你想去探究一二, 蜿蜒的石板街道路通向老城的各個區域, 走着走着, 彷彿時光穿越去了幾百年前在電影情節見到的情景, 小巷錯縱復雜的小巷,路邊攤販、巴剎, 像是身處一千零一夜的場景裡去了 #穆罕默德五世陵墓 #白色古城得土安 【編輯聲明】 本篇文章、相片版權屬作者所有,經由版權持有人授權CyberCTM.com發表。 聯絡及邀約 irene801802@hotmail.com