柚子快報邀請碼778899分享:java 北航OO第三單元總結(jié)
柚子快報邀請碼778899分享:java 北航OO第三單元總結(jié)
1.測試過程
1.1黑箱測試與白箱測試
黑箱測試是一種測試方法,測試者不需要了解軟件內(nèi)部結(jié)構(gòu)或?qū)崿F(xiàn)細節(jié)。測試者關(guān)注的是軟件的功能和行為是否符合需求規(guī)格說明書的描述。
白箱測試是一種測試方法,測試者需要了解軟件的內(nèi)部結(jié)構(gòu)和實現(xiàn)細節(jié)。測試者基于代碼的邏輯路徑、分支條件、循環(huán)等編寫測試用例,以確保代碼的所有部分都被覆蓋和測試。主要是程序開發(fā)者對代碼的正確性進行檢查的方法。
優(yōu)缺點:
黑箱測試:關(guān)注軟件功能,不關(guān)心內(nèi)部實現(xiàn),適合驗證需求和用戶體驗。能有效發(fā)現(xiàn)輸入輸出相關(guān)的缺陷,但是不能覆蓋代碼的內(nèi)部邏輯和路徑,可能會遺漏內(nèi)部實現(xiàn)中的一些邊界情況或異常處理。白箱測試:關(guān)注代碼內(nèi)部邏輯和實現(xiàn),適合發(fā)現(xiàn)邏輯錯誤和提高代碼覆蓋率,有助于優(yōu)化代碼質(zhì)量和性能。但編寫和維護測試用例的成本較高以及難以發(fā)現(xiàn)與輸入輸出相關(guān)的問題。
黑箱測試和白箱測試各有優(yōu)缺點,單獨使用可能會有局限性,但結(jié)合使用可以發(fā)揮各自優(yōu)勢,全面保障軟件質(zhì)量。通過合理的測試策略和自動化工具的應(yīng)用,可以提高測試效率,減少軟件缺陷,提升用戶滿意度。
1.2具體測試
單元測試(Unit Testing)
單元測試是針對軟件中最小的可測試部分(單個函數(shù)或方法)不涉及其他模塊進行的測試,來驗證這些基本單元是否按預(yù)期工作。通過單元測試保證每個模塊的正確性來保證最終程序的正確性。個人感覺只要不是代碼邏輯上的錯誤,就可以保證程序的正確性。
功能測試(Functional Testing)
功能測試類似于黑箱測試,驗證軟件的各個功能是否按需求規(guī)格說明書描述的那樣工作。測試者關(guān)注的是功能是否正確實現(xiàn),而不關(guān)心內(nèi)部實現(xiàn)。具有一定的全面性可以覆蓋所有功能和用例,包括主流程和異常流程。
集成測試(Integration Testing)
集成測試是在單元測試之后,驗證多個模塊或組件之間的交互是否正確。目的是發(fā)現(xiàn)接口和集成點的問題。
壓力測試(Stress Testing)
壓力測試是通過增加系統(tǒng)負載來測試系統(tǒng)在高壓條件下的表現(xiàn),比如構(gòu)造數(shù)據(jù)在該程序時間復(fù)雜度最高和超大數(shù)據(jù)的情況下進行測試。目的是評估系統(tǒng)的穩(wěn)定性和性能瓶頸。
回歸測試(Regression Testing)
回歸測試是在軟件修改(增加新功能,修改部分功能)后進行的測試,目的是確保修改沒有引入新的缺陷,且未影響現(xiàn)有功能。
2.架構(gòu)設(shè)計
本單元的設(shè)計框架基本都由
J
M
L
JML
JML給定了,主要就是維護一個社交網(wǎng)絡(luò)(
M
y
N
e
t
w
o
r
k
MyNetwork
MyNetwork),以每個人作為一個節(jié)點,構(gòu)造一個無向圖形成社交網(wǎng)絡(luò)。
2.1整體圖架構(gòu)
2.2社交網(wǎng)絡(luò)維護策略
(一)第一次作業(yè)
在第一次作業(yè)中主要就是以人為節(jié)點構(gòu)建一個無向圖,形成一個社交網(wǎng)絡(luò),也就是是一個采用鄰接表維護的圖。
這次作業(yè)維護的重點在這幾個方法:
i
s
C
i
r
c
l
e
(
)
isCircle()
isCircle():查詢兩節(jié)點(Person)之間是否存在通路
q
u
e
r
y
B
l
o
c
k
S
u
m
(
)
queryBlockSum()
queryBlockSum():查詢該無向圖中連通圖的數(shù)目
q
u
e
r
y
T
r
i
p
l
e
S
u
m
(
)
queryTripleSum()
queryTripleSum():通俗來說就是查詢該連通圖中三個人之間相互聯(lián)通的數(shù)目
q
u
e
r
y
B
l
o
c
k
S
u
m
(
)
queryBlockSum()
queryBlockSum()和
q
u
e
r
y
T
r
i
p
l
e
S
u
m
(
)
queryTripleSum()
queryTripleSum()這兩個方法基本上都依賴于
i
s
C
i
r
c
l
e
(
)
isCircle()
isCircle()方法,但如果動態(tài)處理的話,
q
u
e
r
y
T
r
i
p
l
e
S
u
m
(
)
queryTripleSum()
queryTripleSum()可以在添加關(guān)系和刪除關(guān)系時進行動態(tài)維護。方法如下:
//添加兩個節(jié)點關(guān)系時
public void addTripleSum(MyPerson myPerson1, MyPerson myPerson2) {
for (Person person : myPerson1.getAcquaintance().keySet()) {
if (person.isLinked(myPerson2)) {
tripleSum++;
}
}
}
//刪除兩個節(jié)點的關(guān)系時
public void deTripleSum(MyPerson myPerson1, MyPerson myPerson2) {
for (Person person : myPerson1.getAcquaintance().keySet()) {
if (person.isLinked(myPerson2)) {
tripleSum--;
}
}
}
i
s
C
i
r
c
l
e
(
)
isCircle()
isCircle()方法的維護主要采用并查集的方法,為每個連通圖設(shè)計一個父節(jié)點,每個連通圖只有唯一一個父節(jié)點,當(dāng)判斷兩個節(jié)點是否聯(lián)通時,只要判斷這兩節(jié)點的父節(jié)點是否相同。
return union.isConnected(id1, id2);
public boolean isConnected(int id1, int id2) {
return find(id1) == find(id2);
}
(二)第二次作業(yè)
第二次作業(yè)圖的結(jié)構(gòu)沒有發(fā)生什么變化,主要就是新增了一些功能,具體要求如下:
q
u
e
r
y
S
h
o
r
t
e
s
t
P
a
t
h
(
)
queryShortestPath()
queryShortestPath():查詢兩個節(jié)點之間的最短路徑,首先要判斷兩個節(jié)點是否聯(lián)通
q
u
e
r
y
B
e
s
t
A
c
q
u
a
i
n
t
a
n
c
e
(
)
queryBestAcquaintance()
queryBestAcquaintance():找到一節(jié)點所有聯(lián)通的節(jié)點中關(guān)系最好的節(jié)點,即權(quán)重最大的節(jié)點。前提是保證該節(jié)點有聯(lián)通的節(jié)點。
q
u
e
r
y
C
o
u
p
l
e
S
u
m
(
)
queryCoupleSum()
queryCoupleSum():圖中兩個節(jié)點相互是最好的
B
e
s
t
A
c
q
u
a
i
n
t
a
n
c
e
BestAcquaintance
BestAcquaintance的個數(shù)
q
u
e
r
y
T
a
g
V
a
l
u
e
S
u
m
(
)
queryTagValueSum()
queryTagValueSum():一個人的tag中所有人之間權(quán)值之和
q
u
e
r
y
S
h
o
r
t
e
s
t
P
a
t
h
(
)
queryShortestPath()
queryShortestPath()就是使用
b
f
s
bfs
bfs進行廣度優(yōu)先搜索查找最短路徑。
q
u
e
r
y
B
e
s
t
A
c
q
u
a
i
n
t
a
n
c
e
(
)
queryBestAcquaintance()
queryBestAcquaintance()采用動態(tài)維護,對于每個節(jié)點設(shè)置
private int bestId;
private int maxValue;
在添加關(guān)系和改變關(guān)系,對這兩個值進行更新,也是很好維護的。
q
u
e
r
y
T
a
g
V
a
l
u
e
S
u
m
(
)
queryTagValueSum()
queryTagValueSum()感覺是這次作業(yè)最難維護的方法,采用動態(tài)維護如果遍歷當(dāng)時所有人中的所有tag,那么感覺和最后的雙重循環(huán)的時間復(fù)雜度感覺差不多,大概都是O(n)的復(fù)雜度。我采用的方法是在
p
e
r
s
o
n
person
person類中新維護一個
n
e
w
T
a
g
s
newTags
newTags
private final HashMap
這個
n
e
w
T
a
g
newTag
newTag存放該人在同一個
t
a
g
tag
tag里所有的
t
a
g
tag
tag,當(dāng)我們動態(tài)維護時,只要遍歷這個
n
e
w
T
a
g
s
newTags
newTags,這是不需要遍歷所有的
t
a
g
tag
tag,只需要遍歷部分的
t
a
g
tag
tag,最壞的情況才要遍歷所有的
t
a
g
tag
tag。
注意的細節(jié),因為只有同一個
t
a
g
s
tags
tags里的
t
a
g
tag
tag的
i
d
id
id才會不同,但我們的
n
e
w
T
a
g
s
newTags
newTags里的
t
a
g
tag
tag的
i
d
id
id會有相同的情況,我就為這個
t
a
g
tag
tag新建了一個
i
d
id
id,這個
i
d
id
id只是為了避免重復(fù)和便于查找,沒有其他任何實際意義。
//netWork中的實現(xiàn)
public void addTag(int personId, Tag tag) {
MyPerson myPerson = (MyPerson) getPerson(personId);
myPerson.addTag(tag);
((MyTag) tag).setNewid(idcount);
idcount++;
}
public void addPersonToTag(int personId1, int personId2, int tagId) {
MyTag mytag = (MyTag) getPerson(personId2).getTag(tagId);
if (mytag.getSize() <= 1111) {
mytag.addPerson(getPerson(personId1));
((MyPerson) getPerson(personId1)).addToNewtags(mytag);
}
}
public void delPersonFromTag(int personId1, int personId2, int tagId) {
MyTag mytag = (MyTag) getPerson(personId2).getTag(tagId);
mytag.delPerson(getPerson(personId1));
((MyPerson) getPerson(personId1)).delFromNewTags(mytag);
}
public void addToNewtags(Tag tag) {
this.newTags.put(((MyTag) tag).getNewid(), tag);
}
public void delFromNewTags(Tag tag) {
this.newTags.remove(((MyTag) tag).getNewid());
}
//這步開始遍歷,并修改valueSum的值
public void find(MyPerson myPerson, int value) {
for (Tag tag : newTags.values()) {
if (tag.hasPerson(myPerson)) {
((MyTag) tag).changeValue(value);
}
}
}
(三)第三次作業(yè)
這次迭代就是發(fā)消息,這次作業(yè)沒有什么需要特殊維護的地方,只要讀懂
J
M
L
JML
JML的規(guī)格就行了,還有就是注意一些細節(jié)的實現(xiàn)基本上就沒什么問題了。
3.性能問題分析
3.1性能問題及其修復(fù)情況
我的代碼實現(xiàn)基本都使用動態(tài)維護的方式,前面都介紹過了,這里不再贅述,動態(tài)維護寫的基本上都可以通過強測,感覺性能上沒啥太大的問題,
q
u
e
r
y
T
a
g
V
a
l
u
e
S
u
m
(
)
queryTagValueSum()
queryTagValueSum()采用了空間換時間的方式來優(yōu)化性能,其他需要雙重甚至三重循環(huán)的地方都采用動態(tài)維護的方式進行性能優(yōu)化。強測性能沒有問題,也沒有做任何修復(fù)。
3.2規(guī)格與實現(xiàn)分離
規(guī)格與實現(xiàn)分離是軟件開發(fā)中的一種設(shè)計原則,其核心思想是將軟件系統(tǒng)的規(guī)格(
J
M
L
JML
JML或需求)與實現(xiàn)(或代碼)分開,以實現(xiàn)更好的可維護性、可擴展性和可重用性。規(guī)格與實現(xiàn)分離通過清晰地定義規(guī)格并將其與具體的實現(xiàn)分開,可以提高軟件系統(tǒng)的可維護性、可擴展性和可重用性,降低系統(tǒng)的耦合度,從而更有效地開發(fā)和維護高質(zhì)量的軟件系統(tǒng)。
4.
J
u
n
i
t
Junit
Junit測試方法
我的
J
u
n
i
t
Junit
Junit測試方法主要包括構(gòu)造測試數(shù)據(jù)、驗證前置條件、運行測試方法、驗證后置條件。
我在構(gòu)造測試數(shù)據(jù)時,創(chuàng)建兩個完全相同的
N
e
t
w
o
r
k
Network
Network,這樣就實現(xiàn)了深拷貝的方法,對于其中一個的
N
e
t
w
o
r
k
Network
Network的通過
J
M
L
JML
JML規(guī)格保證前置條件的正確性,在調(diào)用代碼中的測試方法,得到新的
N
e
t
w
o
r
k
Network
Network和后置條件,通過比較這兩個結(jié)果是否
e
q
u
a
l
equal
equal來檢測代碼的正確性。
感覺這幾次的
J
u
n
i
t
Junit
Junit測試的難點在于數(shù)據(jù)的構(gòu)造,要保證數(shù)據(jù)盡可能地覆蓋所有的可能性,既要有稠密圖也要有稀疏圖,發(fā)送消息時也要考慮到所有的信息和發(fā)送的次數(shù)。
5.學(xué)習(xí)體會
這個單元的按照規(guī)完成代碼,雖然以后不是很常用,但是這種按照規(guī)格來寫代碼,保證這個方法的正確性,這種寫法感覺挺好的。但是這種模式只是給你最終實現(xiàn)的結(jié)果,具體的實現(xiàn)還得靠程序員,有時寫的代碼完全不同于規(guī)格所描述的,只是最終的結(jié)果符合他的規(guī)格敘述。
還有就是
J
u
n
i
t
Junit
Junit的編寫感覺還是有點麻煩,希望課程組可以在后期的課程中給一點關(guān)于
J
u
n
i
t
Junit
Junit測試的提示。
柚子快報邀請碼778899分享:java 北航OO第三單元總結(jié)
文章鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。