軟件單元測試技巧_第1頁
軟件單元測試技巧_第2頁
軟件單元測試技巧_第3頁
軟件單元測試技巧_第4頁
軟件單元測試技巧_第5頁
已閱讀5頁,還剩54頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、單元測試,Brief Agenda,程序員為什么要做測試 測試的一些基本概念 測試先行的概念 單元測試的基本做法和常見工具,測試不是我的工作 你是這樣的程序員么?,測試是測試部門的責(zé)任,我的責(zé)任應(yīng)該關(guān)注在寫代碼上 測試不是一種技術(shù)工作,毫無樂趣可言,請不要騷擾我。我可是一個了不起的EJB程序員 我們有測試人員,有集成/系統(tǒng)/確認(rèn)測試,他們遲早會發(fā)現(xiàn)我的錯誤。請不要浪費(fèi)我的時間。 不要侮辱我,我寫的程序,怎么可能有錯誤。測試是完全沒必要的。,離我遠(yuǎn)一點(diǎn),我是程序員,你做了測試了嗎?,大部分中小公司,和軟件開發(fā)管理處于早期階段的團(tuán)隊(duì),沒有專門的測試工作和測試流程,測試只是在產(chǎn)品提交給用戶之前,組織

2、若干人員對最終產(chǎn)品作一次基本功能的確認(rèn)測試而已。更多時候,測試的實(shí)際工作是用戶來完成的。,后果,軟件的質(zhì)量完全取決于程序員的個人技能和責(zé)任心,具有很大的隨機(jī)性 后期維護(hù)成本高昂 1個月的開發(fā),幾天的測試,然后花1,2年的時間去修補(bǔ)錯誤 這個項(xiàng)目我已經(jīng)維護(hù)了3年了 根本原因是軟件自身復(fù)雜的結(jié)構(gòu),蟲蟲和天上的星星一樣多,軟件的結(jié)構(gòu),方法,類,功能,模塊,系統(tǒng),用戶需求,系統(tǒng)結(jié)構(gòu),集成,單元,錯誤可能會隨機(jī)的分布在任何一個地方,測試模型,軟件自身的復(fù)雜程度決定了即使是最優(yōu)秀的程序員也不可能不制造任何錯誤。 軟件自身的復(fù)雜程度決定了不可能只通過對最終產(chǎn)品的1,2種類型的測試就可以排除系統(tǒng)中的大部分錯誤

3、 測試必須并行的融入到軟件開發(fā)生命周期的各個階段,以覆蓋軟件結(jié)構(gòu)和開發(fā)生命周期的不同關(guān)注點(diǎn)。 主要的模型有傳統(tǒng)的瀑布模型,和v模型,以及改良的x模型,V模型,測試活動融入整個軟件開發(fā)的生命周期 不同階段的測試強(qiáng)調(diào)的是從不同視角關(guān)注不同的方面,盡可能早而全的出去錯誤,不累計(jì)錯誤。 每一種類型測試的效果,將嚴(yán)格依賴于前期階段其他類型測試的執(zhí)行的正確,完整與否。 測試有分工,合適的人在合適的時候承擔(dān)合適的測試 改良的有x模型,時間和成本,缺陷的發(fā)現(xiàn)時間越晚,修復(fù)的成本越高,在部署階段每個缺陷的修復(fù)成本都會及其高昂(每一個major以上的缺陷修復(fù)都不得不作完整的系統(tǒng)測試和確認(rèn)測試),嚴(yán)格實(shí)施scm的組

4、織尤其昂貴。,什么是單元測試,單元測試測試的軟件最小的可執(zhí)行單元的正確性,即類或方法 單元測試通常是一段可執(zhí)行代碼,并能驗(yàn)證執(zhí)行結(jié)構(gòu)是否和預(yù)期相等 每個單元測試至少應(yīng)該有兩個測試?yán)? Test Case ): Negative/Positive 單元測試可以是黑盒也可以是白盒,取決于執(zhí)行方法,蓋房子,至少要保證每一塊磚都是好的,什么是單元測試(Unit Test),單元測試是其他類型測試的基礎(chǔ)。不認(rèn)真,完整的單元測試會導(dǎo)致其他類型測試起不到好的效果 程序員最了解自己的程序單元,最適合做單元測試 傳統(tǒng)的重量級的方法學(xué)里,UT test case由設(shè)計(jì)人員在系統(tǒng)設(shè)計(jì)階段開發(fā),并用來驗(yàn)證編碼人員的

5、工作質(zhì)量,蓋房子,至少要保證每一塊磚都是好的,單元測試是成本最低的測試活動,發(fā)現(xiàn)一個Defect所需要的時間 91年數(shù)據(jù),程序員的責(zé)任,程序員的價值在于和他人合作,開發(fā)出高質(zhì)量的代碼,而不是一堆新技術(shù)名詞堆砌的蟲件(bugware)。 程序員必須對自己的代碼質(zhì)量負(fù)責(zé),單元測試是對自己代碼質(zhì)量的基本承諾。 程序=UT+CODE 不做單元測試,就會影響團(tuán)隊(duì)其他人員的工作。測試人員有權(quán)利對沒有做過UT的代碼說No.不愿意做UT的人,不屬于任何團(tuán)隊(duì)。,程序=UT + CODE,實(shí)踐證明(個人工作經(jīng)歷),代碼質(zhì)量最好的程序員是UT做的最好的程序員。 開發(fā)速度最快的程序員,是UT做的最好的程序員 80%以

6、上的非需求性錯誤,都集中在沒有做UT和不方便做UT的代碼塊。 UT的質(zhì)量直接影響了IT/ST/UAT的質(zhì)量。,程序=UT + CODE,測試很重要,但是,我已經(jīng)調(diào)試運(yùn)行過代碼了,他應(yīng)該是正確的,為什么還要浪費(fèi)額外的時間 程序已經(jīng)能跑起來了,這期間我實(shí)際已經(jīng)手工作了測試,只是沒有記錄和編寫代碼而已 我沒有時間做測試,工期已經(jīng)很緊張了,能寫完代碼就不錯了,雖然我知道以后要返工。 我不知道應(yīng)該怎么樣去做測試,調(diào)試不等于UT,調(diào)試只會關(guān)注于程序的某個方面,通常是最優(yōu)路徑。UT至少要關(guān)注正/負(fù)2個方面,還需要保證一定的覆蓋率 調(diào)試,尤其是J2EE應(yīng)用的調(diào)試要耗費(fèi)大量的時間,沒有UT的效率高(后面再細(xì)講)

7、 調(diào)試不可重現(xiàn),在代碼變跟以后,軟件質(zhì)量無法保證,UT一定要做到自動化,只有用代碼編寫的UT,才能夠重現(xiàn),才能真正節(jié)約未來手工測試的時間。 只有用代碼編寫的UT ,才能做到自動化,才能在軟件開發(fā)的任何時候都能快速,簡單的大批量執(zhí)行,保證能準(zhǔn)確地定位錯誤,保證不會因?yàn)樾薷亩胄碌腻e誤。在系統(tǒng)開發(fā)的后期尤為明顯。 自動化的UT,才能保證回歸測試的有效執(zhí)行。,UT節(jié)約的是你未來的時間,編寫UT代碼的時間節(jié)約了未來修改/維護(hù)低質(zhì)量代碼的時間 學(xué)習(xí)做UT的時間,是為了以后你可以更好的關(guān)注你的代碼 如果使用Test-driven的思想 自身就變成設(shè)計(jì)的一部分,你不會再感到是在浪費(fèi)時間,編寫UT的過程,就

8、是設(shè)計(jì)的過程 UT快速的定位錯誤所在,節(jié)約了你調(diào)試的時間。,需求,設(shè)計(jì),評審,編碼,rework,UT,如何進(jìn)行UT -傳統(tǒng)的做法,在it之前進(jìn)行UT,嚴(yán)格的瀑布模型,UT作為生命周期的一個階段 UT 的Test Case一般做為設(shè)計(jì)的一部分。 UT的執(zhí)行通常在代碼review以后 Test case單獨(dú)編寫和執(zhí)行 成本高昂,尤其是嚴(yán)格執(zhí)行SCM的情況。 UT本身是作為一種最終的質(zhì)量檢測手段,只能節(jié)約未來的時間. 完整全面的UT 需要大量的時間,精力,需要和PR結(jié)合 程序員通常感覺不到UT帶來的眼前好處,得不到任何樂趣,抵制執(zhí)行。,如何進(jìn)行UT -傳統(tǒng)的做法 *場景,程序員先開始設(shè)計(jì)數(shù)據(jù)表。然

9、后開始依次編寫數(shù)據(jù)訪問對象,strust action,jsp頁面。他檢查了一遍代碼,確定每件事看起來都是不錯的,于是他開始把所有的東西集成在一塊。當(dāng)然,通常是跑不起來的,經(jīng)過若干個小時辛苦的調(diào)試,中間不斷的修改代碼,重起app server。終于在數(shù)據(jù)訪問對象中發(fā)現(xiàn)了一個錯誤。 若干時間以后,在代碼被review以后,程序員開始做枯燥無味的單元測試工作,這個時候,他最想做的事情其實(shí)是睡覺。,迫于時間和成本的壓力,pm/程序員往往會簡化或者不執(zhí)行UT的過程,需求,設(shè)計(jì),運(yùn)行ut,定位錯誤,編碼,rework,編寫Test case,如何進(jìn)行UT -改良, 寫一點(diǎn),測一點(diǎn),程序員每編寫完一個程序

10、單元,就編寫UT代碼 首先通過運(yùn)行UT代碼來定位程序的錯誤,而不是直接調(diào)試代碼,節(jié)約了大量調(diào)試的時間。 如果能把程序劃分為盡可能小的單元,通過執(zhí)行ut代碼,就能快速的定位錯誤的所在,調(diào)試就可以避免 可有效的保證以前編寫的代碼的正確性,不需要拖到增量結(jié)束以后再執(zhí)行。 錯誤能盡早的發(fā)現(xiàn),不需要等到Code review以后再修復(fù),成本很低,Code review,如何進(jìn)行UT -改良, 寫一點(diǎn),測一點(diǎn),程序員開始設(shè)計(jì)數(shù)據(jù)庫表,然后開始編寫數(shù)據(jù)訪問對象,接著他對數(shù)據(jù)訪問對象編寫了UT test case,運(yùn)行TC,發(fā)現(xiàn)了若干錯誤,然后迅速的改正了他。所有的TC都通過以后,他開始編寫ACTION,同樣

11、,他對ACTION做了些測試。最后他編寫了JSP,并把所有的東西集成在一起,當(dāng)然因?yàn)镴SP的不好測試性,他花了點(diǎn)時間在修訂JSP頁面的幾個TAG錯誤上。 若干時間以后,在做IT之前,他去問QA部門的人,你看,我所有的代碼都寫了UT TC,這些TC能不能直接作UT的REPORT呢?在得到確定的回到以后,他很高興得回去做別的事了。,UT作為一種幫助提高開發(fā)效率的有效手段融入到開發(fā)過程中,程序員也不需要再去做枯燥無聊的事后UT了,如何進(jìn)行UT -改良, 寫一點(diǎn),測一點(diǎn) .實(shí)踐,在一段時間以后,我發(fā)現(xiàn)如果自己不寫UT,我的開發(fā)速度就開始大打折扣 我的一位同事在1個月以后,很樂于向我展示作UT的好處。每

12、次他做任何修改,他都可以通過執(zhí)行所有UT的SUITE來確保沒有引入任何新的錯誤,節(jié)約了大量的時間,看到屏幕上的一排綠燈,那種心情非常好。 “整個團(tuán)隊(duì)只有我能按時下班,終于CTO問我為什么,我告訴他,我總是在做UT,所以我很少化時間去做調(diào)試?!?編程的80%時間都是用在調(diào)試,節(jié)約了調(diào)試的時間,也就提高了開發(fā)的速度,每次看到綠燈的時候,心情就很好,如何進(jìn)行UT -改良, 寫一點(diǎn),測一點(diǎn) 缺點(diǎn),經(jīng)常性的,當(dāng)你寫完一個方法,你或許過于自信,而不愿意再去為他寫一個test case.若干時間以后,你發(fā)現(xiàn)他的問題終于出來了 有時候,當(dāng)辛苦編寫完代碼,開始編寫test case的時候,你會發(fā)現(xiàn)因?yàn)樵O(shè)計(jì)上錯誤

13、,這段代碼是不可以測試的。這就為未來留下了隱患,如何進(jìn)行UT 測試驅(qū)動的做法,設(shè)計(jì),先寫 單元測試,重構(gòu),運(yùn)行 單元測試,編程,發(fā)現(xiàn)BUG,如何進(jìn)行UT 測試驅(qū)動的做法,先寫Test case,可以保證我們每一個public/protected的方法都確實(shí)有Test Case 編寫 test case的過程也就是一個設(shè)計(jì)的過程 你需要考慮實(shí)現(xiàn)代碼的可測試行 你需要考慮代碼和測試代碼的關(guān)系,仔細(xì)考慮實(shí)現(xiàn)代碼的邊界和邏輯,測試代碼應(yīng)該如何保證實(shí)現(xiàn)代碼的正確性當(dāng)測試代碼完成的時候,就會對實(shí)現(xiàn)代碼有清晰地了解 你仔細(xì)思考要做什么和不要做什么,可以避免過度設(shè)計(jì) 此時的UT實(shí)際是白盒測試,能起到更好的效果

14、??梢园殃P(guān)注點(diǎn)放在某些重要的地方。,Example 通過測試代碼來思考設(shè)計(jì),/空置必須拋出異常 Try boy.add(null); fail(“dont throw exception ”); catch (xxx) / add / boy.add(new Boy(); String id = boy.add(new Boy(); /需要檢測是否增加成功,那么add就應(yīng)該返回id值,修改上面的代碼 assertEqual(id, boy.find(id).getID(),If (value = null) throw new IllegalArguementException(xxx); S

15、tring id = DAOSupport.addObject(boy); Return id;,Test case,add,如何進(jìn)行UT 測試驅(qū)動的做法,Test-Driven Design是一種開發(fā)風(fēng)格,它要求程序員做到: 在寫產(chǎn)品代碼之前,先寫它的單元測試( Unit Tests ) 沒有單元測試的Class不允許作為產(chǎn)品代碼 單元測試?yán)記Q定了如何寫產(chǎn)品代碼 不斷地成功運(yùn)行所有的單元測試?yán)?不斷的完善單元測試?yán)?Test-Driven Design是把需求分析,設(shè)計(jì),質(zhì)量控制量化的過程!也是一個對軟件持續(xù)改進(jìn)的過程,如何進(jìn)行UT 測試驅(qū)動的做法,測試代碼/實(shí)現(xiàn)代碼的交替編寫,能讓大

16、腦始終處在一種松馳/緊張,工作效率會比較高。 編寫測試代碼也是設(shè)計(jì)的過程,總體的時間花費(fèi)就下降了,也避免了因?yàn)閷Σ豢蓽y試代碼的修改而導(dǎo)致的時間成本,文物之道,一張一弛,常用單元測試框架,JUnit Struts test case, junit的擴(kuò)展,用于測試struts的action HttpUnit 測試http頁面 JFC Unit. Cactus 專門用來測試服務(wù)器類 JsUnit 測試javascript,JUnit,一個開源的單元測試框架,也是其他java單元測試框架的基礎(chǔ),JUnit Test case,public class TestPerson extends TestCa

17、se /* A unit test to verify the name is formatted correctly. */ public void testGetFullName( ) Person p = new Person(Aidan, Burke); assertEquals(Aidan Burke, p.getFullName( ); /* A unit test to verify that nulls are handled properly. */ public void testNullsInName( ) Person p = new Person(null, Burk

18、e); assertEquals(? Burke, p.getFullName( ); / this code is only executed if the previous assertEquals p = new Person(Tanner, null); assertEquals(Tanner ?, p.getFullName( ); ,Test case 擴(kuò)展自TestCase,每個方法負(fù)責(zé)對某種情況測試,測試結(jié)果為true/false,JUnit assertXXX( ),使用一系列的assertXXX方法來判斷執(zhí)行結(jié)果是否和預(yù)期相符,不符則執(zhí)行失敗,不會再繼續(xù)case(當(dāng)前方法)

19、的余下部分,Junit Test Case,執(zhí)行結(jié)果將顯示一次運(yùn)行通過/不通過的TC數(shù)目,通常很快??梢园讯鄠€TC集合成一個suite一起測試.和ANT這類的工具配合還可以自動生成測試報告,JUnit Set Up and Tear Down,setUp() 提供初始化方法 tearDown提供清除方法 如果幾個測試case(方法)共享同樣的初始化合清除方法,如dao對象的創(chuàng)建,可以使用setUp/tearDown方法 如果需要在幾個test方法中共享某一個變量,請使用static的類變量,因?yàn)閖unit為每個方法都重新創(chuàng)建一個對象。,setUp(),TestXXX(),tearDown,JU

20、nit One-Time Set Up and Tear Down,public class TestPerson extends TestCase public void testGetFullName( ) . public void testNullsInName( ) . public static Test suite( ) TestSetup setup = new TestSetup(new TestSuite(TestPerson.class) protected void setUp( ) throwsException / do your one-time setup he

21、re! protected void tearDown( ) throws Exception / do your one-time tear down here! ; return setup; ,某些情況下,我們希望一組test case的setup/tear down僅僅運(yùn)行一次,通常是為了提高速度,可以使用此種做法 在這種情況,如果為TestPerson自己實(shí)現(xiàn)了setup/tearDown方法,他們還是會被執(zhí)行的。,JUnit Repeating Tests,public static Test suite( ) / run the entire test /suite ten ti

22、mes return new RepeatedTest(new TestSuite(TestGame.class), 10); ,如果想重復(fù)的運(yùn)行某個測試若干次,可用此法,可用此法來制造模擬數(shù)據(jù)或性能測試,JUnit Organizing Tests into Test Suites,public class TestGame extends TestCase . public static Test suite( ) return new TestSuite(TestGame.class); public static Test suite( ) TestSuite suite = new

23、TestSuite( ); suite.addTest(new TestGame(testCreateFighter); suite.addTest(new TestGame(testSameFighters); return suite; ,Test suite的目的是把所有的test case放在一起執(zhí)行。為了驗(yàn)證程序的其他部分,或者作night test,我們通常需要構(gòu)造test suites 第一種方法將自動執(zhí)行testGame所有的testXXX方法 第二種方法只執(zhí)行指定的方法,JUnit Exception Handling,public void testPassNullsToC

24、onstructor( ) try Person p = new Person(null, null); fail(“xxx); catch (IllegalArgumentException expected) / its ok / dont do this! public void testBadStyle( ) try SomeClass c = new SomeClass( ); c.doSomething( ); catch (IOException ioe) fail(Caught an IOException); ,如果期盼代碼拋出某種異??梢允褂玫谝环N做法 對不期盼處理的異???/p>

25、以直接拋出,不要做try catch處理,junit會自動轉(zhuǎn)為fail,JUnit Running Tests Concurrently,public static Test suite( ) TestSuite suite = new ActiveTestSuite( ); suite.addTest(new TestGame(testCreateFighter); suite.addTest(new TestGame(testGameInitialState); suite.addTest(new TestGame(testSameFighters); return suite; ,要求同

26、時跑多個線程,可以使用ActiveTestSuite來啟動,此法可對多線程應(yīng)用進(jìn)行測試,JUnit 測試的命名規(guī)范,/* * TGID 001 /測試組id * 這個類測試XXX */ Class XxxTest /測試類以Test屆尾 /* TCID 001 /測試case id 此方法測試 xxxxx */ public void testXXX() /測試方法以test開頭 ,遵守規(guī)范的命名可以方便作night test和最后用javadoc/java2hmtl提出文檔,作UT report,JUnit,/ add user String id = Dao.add(boy); / con

27、firm the result of add op boy = dao.findByID(id); assertNotNull(boy); / add the existed user. Negative test Dao.add(boy);,測試CASE的考慮應(yīng)該全面,至少要檢測方法的執(zhí)行效果,也要從正反2面進(jìn)行考慮. 否則就起不到效果。,JUnit integerated with eclipse,將Junit集成到eclipse要做以下工作(確省已經(jīng)安轉(zhuǎn)) 下載相應(yīng)的插件文件org.junit,org,eclipse.jdt.junit 將該文件解壓到eclipse_install_di

28、rplugins 重新啟動eclipse 將junit.jar加入項(xiàng)目的classpath,也就是build lib里,JUnit integerated with eclipse,新建junit的test case 選擇run as junit test運(yùn)行 也可選擇debug,可以對細(xì)節(jié)進(jìn)行跟蹤調(diào)試,JUnit struts test case,Junit的擴(kuò)展,提供對struts框架action的測試 主要有2種方式 使用mock object 使用cactus框架,JUnit struts test case with Mock object,public class TestLogi

29、nAction extends MockStrutsTestCase public void testSuccessfulLogin() setRequestPathInfo(/login); addRequestParameter(username,deryl); addRequestParameter(password,radar); actionPerform(); /執(zhí)行struts的action verifyForward(success); assertEquals(deryl,(String) getSession().getAttribute(authentication);

30、verifyNoActionErrors(); ,Test case 從MockStrustTestCase擴(kuò)展,JUnit struts test case with Mock object,提供一部分的模擬方法如addRequestParameter來進(jìn)行模擬web調(diào)用 增加了若干成功判斷方法。 如verifyForward(), verifyNoActionErrors()針對struts的forward,action error處理等 使用mock 對象,可以不使用web環(huán)境,配置簡單 應(yīng)該將邏輯從action移走,避免針對action的大量邏輯測試,Cactus(http:/jaka

31、/cactus ),主要提供對server-side的java code的測試,也提供對EJB/JSP tag 的單元測試,Cactus設(shè)置,Client端classpath需要包括junit.jar, cacturs.jar,httpclient.jar,aspectjrt.jar,common-logging.jar,可選配置httpunit.jar,tidy.jar,xercex.jar 客戶端需要有perties 描述基本配置,也要在classpath中能找到 cactus.contextURL=http:/localhost:8080/

32、xptest cactus.servletRedirectorName=ServletRedirector cactus.jspRedirectorName=JspRedirector cactus.filterRedirectorName=FilterRedirector 服務(wù)器端需要包括測試用列和上述類,Cactus web.xml的配置, ServletRedirector org.apache.cactus.server.ServletTestRedirector ServletRedirector /ServletRedirector ,可以針對servlet/jsp/filter三

33、種情況進(jìn)行配置,peries里面的項(xiàng)目要和此對應(yīng),Example,public class SimpleJspTest extends ServletTestCase public void beginValidFormParameters(WebRequest webRequest) webRequest.addParameter(username, coyner_b, WebRequest.POST_METHOD); webRequest.addParameter(password, secret, WebRequest.POST_METHOD); public void testValidFormParameters( ) assertTrue(Valid Parameters., this.servlet.validateParameters(this.request); ,beginXXX, endXXX方法僅在在客戶端執(zhí)行,單元測試的質(zhì)量,通常使用測試通過率和測試覆蓋率2項(xiàng)指標(biāo) 測試通過率必須是100%,表明所有test都通過 測試覆蓋率有語句/路徑/條件/分支等等,一般要求語句100%覆蓋,路徑60%左右覆蓋??梢怨烙?jì)你大致的測試力度。 可以用jtest/nounit這樣的工具來獲得這些指標(biāo),提示,盡可能

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論