JUnit :: 或如何喜歡 JavaRush 驗證器
簡要說明為什麼我們需要這個野獸?JUnit是一個用來自動測試好程式碼或不太好程式碼的框架。你可以說: - 為什麼我需要這個 swing,我可以輕鬆簡單地測試我好的 Java 程式碼。你可以寫很多介紹性的歌詞,但我不是什麼詩人,咱們言歸正傳吧…創建一個對象
因此,為了測試某些東西,我們首先需要一個測試物件。我們面前有一項任務。- 我們需要一個物件來儲存有關用戶的信息。
- Id - 必須按照新增使用者的順序進行計數。
- 使用者名稱.
- 他的年齡。
- 性別(男/女)
-
有必要提供用戶清單的儲存。
-
班級一定可以。
- 產生所有使用者的列表。
- 按性別(男性/女性)產生使用者清單。
- 傳回總列表中使用者的數量,並根據使用者的性別計算數量。
- 以使用者年齡計算總金額,並考慮性別。
- 計算總體平均年齡和按性別劃分的平均年齡。
User
包含欄位的 Java 類別:
private int id;
private String name;
private int age;
private Sex sex;
這足以儲存用戶數據,讓我們看看該任務還需要什麼。我們需要以某種方式儲存所有用戶,讓我們在我們的類別中建立一個靜態字段allUsers
,我認為如果是的話可以Map<Integer, User>
private static Map<Integer, User> allUsers;
我們還需要以某種方式為用戶分配一個序號,讓我們建立一個靜態計數器字段,當創建新用戶時,它將Id
為該用戶分配一個序號。
private static int countId = 0;
所以,我們似乎已經整理好了字段,讓我們為我們的物件編寫一個建構函數,並為字段id
, name
, age
,編寫 getter sex
。heterae 沒什麼複雜的,我們向IDEA尋求幫助吧,她永遠不會拒絕,我們會讓建構子變得有點棘手。設計師一定能夠做到。初始化字段,檢查 中是否有這樣的對象allUsers
,如果沒有這樣的對象,則增加我們的計數器countId++
並將其添加到所有用戶的列表中。allUsers
如果該欄位尚未初始化,則也要初始化該欄位。為了方便搜尋相同的對象,我們將重新定義方法,equals()
並且再次向我們心愛的IDEAhashCode()
尋求幫助並按字段進行比較,,。另外,讓我們建立一個私有方法來檢查這樣的物件是否在列表中。 name
age
sex
hasUser()
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age &&
Objects.equals(name, user.name) &&
sex == user.sex;
}
@Override
public int hashCode() {
return Objects.hash(name, age, sex);
}
最後,我遇到了這樣的設計師。
public User(String name, int age, Sex sex) {
if (allUsers == null){
allUsers = new HashMap<>();
}
this.name = name;
this.age = age;
this.sex = sex;
if (!hasUser()){
countId++;
this.id = countId;
allUsers.put(id, this);
}
}
和一個私人輔助方法
private boolean hasUser(){
for (User user : allUsers.values()){
if (user.equals(this) && user.hashCode() == this.hashCode()){
return true;
}
}
return false;
}
並且也重新定義toString()
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
現在是時候實作所需方法的邏輯了。由於邏輯主要使用靜態字段,因此我們也將方法設為靜態;物件不需要它們。
- 產生所有使用者的列表。
- 按性別(男性/女性)產生使用者清單。
-
傳回總列表中使用者的數量,並根據使用者的性別計算數量。
public static int getHowManyUsers(){ return allUsers.size(); } public static int getHowManyUsers(Sex sex){ return getAllUsers(sex).size(); }
-
以使用者年齡計算總金額,並考慮性別。讓我們為此任務創建方法。
public static int getAllAgeUsers(){ int countAge = 0; for (User user : allUsers.values()){ countAge += user.age; } return countAge; } public static int getAllAgeUsers(Sex sex){ int countAge = 0; for (User user : getAllUsers(sex)){ countAge += user.age; } return countAge; }
-
計算總體平均年齡和按性別劃分的平均年齡。
public static int getAverageAgeOfAllUsers(){ return getAllAgeUsers() / getHowManyUsers(); } public static int getAverageAgeOfAllUsers(Sex sex){ return getAllAgeUsers(sex) / getHowManyUsers(sex); }
太好了,我們已經描述了所需的物件及其行為。現在我們可以繼續使用JUnit ,但首先我將向您展示如果我們在main中進行簡單測試會是什麼樣子。
public static void main(String[] args) { new User("Eugene", 35, Sex.MALE); new User("Marina", 34, Sex.FEMALE); new User("Alina", 7, Sex.FEMALE); System.out.println("All users:"); User.getAllUsers().forEach(System.out::println); System.out.println("All users: MALE"); User.getAllUsers(Sex.MALE).forEach(System.out::println); System.out.println("All users: FEMALE"); User.getAllUsers(Sex.FEMALE).forEach(System.out::println); System.out.println("================================================"); System.out.println(" all users: " + User.getHowManyUsers()); System.out.println(" all MALE users: " + User.getHowManyUsers(Sex.MALE)); System.out.println("all FEMALE users: " + User.getHowManyUsers(Sex.FEMALE)); System.out.println("================================================"); System.out.println(" total age of all users: " + User.getAllAgeUsers()); System.out.println(" total age of all MALE users: " + User.getAllAgeUsers(Sex.MALE)); System.out.println("total age of all FEMALE users: " + User.getAllAgeUsers(Sex.FEMALE)); System.out.println("================================================"); System.out.println(" average age of all users: " + User.getAverageAgeOfAllUsers()); System.out.println(" average age of all MALE users: " + User.getAverageAgeOfAllUsers(Sex.MALE)); System.out.println("average age of all FEMALE users: " + User.getAverageAgeOfAllUsers(Sex.FEMALE)); System.out.println("================================================"); }
控制台的輸出看起來像這樣,然後我們將比較是否正常運作。當然,我們可以更深入地編寫比較邏輯,並查看我們的計算結果,即使我們不確定我們是否能夠提供所有內容。
//output Все пользователи: User{id=1, name='Eugene', age=35, sex=MALE} User{id=2, name='Marina', age=34, sex=FEMALE} User{id=3, name='Alina', age=7, sex=FEMALE} Все пользователи: MALE User{id=1, name='Eugene', age=35, sex=MALE} Все пользователи: FEMALE User{id=2, name='Marina', age=34, sex=FEMALE} User{id=3, name='Alina', age=7, sex=FEMALE} ================================================ всех пользователей: 3 всех пользователей MALE: 1 всех пользователей FEMALE: 2 ================================================ общий возраст всех пользователей: 76 общий возраст всех пользователей MALE: 35 общий возраст всех пользователей FEMALE: 41 ================================================ средний возраст всех пользователей: 25 средний возраст всех пользователей MALE: 35 средний возраст всех пользователей FEMALE: 20 ================================================ Process finished with exit code 0
我們對這個結果並不滿意,在主要測試結束後,我們需要JUnit。
點a和bgetAllUsers()
可以透過傳回 all 列表的方法和傳回列表的User
重載方法來很好地處理,具體取決於傳遞的參數。getAllUsers(Sex sex)
Sex
public static List<User> getAllUsers(){
return new ArrayList<>(allUsers.values());
}
public static List<User> getAllUsers(Sex sex){
List<User> listAllUsers = new ArrayList<>();
for (User user : allUsers.values()){
if (user.sex == sex){
listAllUsers.add(user);
}
}
return listAllUsers;
}
如何將 JUnit 連接到項目
問題是如何將其連接到項目。對於那些了解情況的人來說,我不會選擇Maven,因為這是一個完全不同的故事。;) 開啟專案結構 Ctrl + Alt + Shift + S -> Libraries -> 點擊 + (New Project Library) -> select from Maven, 然後我們看到這樣一個窗口,在搜尋欄中輸入“junit:junit:4.12” ,等到找到->確定!-> 好的! 您應該得到這個結果 點擊 OK,恭喜 JUnit 已加入專案。讓我們繼續。現在我們需要為 Java 類別建立測試,將遊標放在類別的名稱上User
-> 按 Alt + Enter -> 選擇建立測試。我們應該看到一個窗口,在其中我們需要選擇 JUnit4 庫 -> 選擇我們要測試的方法 -> OK 這個想法本身將創建一個類UserTest
,在這個類中我們將用測試覆蓋我們的程式碼。讓我們開始吧:
我們的第一個@Test
讓我們創建第一個@Test方法getAllUsers()
- 這是一個應該返回所有用戶的方法。測試將如下所示:
@Test
public void getAllUsers() {
// create test data
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
//create an expected list and fill it with the data of our method
List<User> expected = User.getAllUsers();
//create actual list put data in it for comparison
//what we expect the method to return
List<User> actual = new ArrayList<>();
actual.add(user);
actual.add(user1);
actual.add(user2);
//run the test if the list expected and actual are not equal
//the test will fail, read the test results in the console
Assert.assertEquals(expected, actual);
}
這裡我們創建幾個測試用戶 -> 創建一個列表expected
,我們將在其中放置其方法將返回給我們的用戶getAllUsers()
-> 創建一個列表actual
,在其中我們將放置我們假設 Assert.assertEquals getAllUsers()
(actual, Expected) 方法的用戶將被使用,我們將把檢查過的和當前的列表傳遞給它。此方法將測試提供的清單中的物件並傳回測試結果。該方法將比較物件的所有字段,如果存在繼承,甚至會遍歷父物件的字段。讓我們執行第一個測試... 測試成功完成。現在讓我們嘗試讓測試失敗,為此我們需要更改其中一個測試列表,我們將透過註解掉向列表新增一個使用者來實現此目的actual
。
@Test
public void getAllUsers() {
// create test data
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
//create an expected list and fill it with the data of our method
List<User> expected = User.getAllUsers();
//create actual list put data in it for comparison
//what we expect the method to return
List<User> actual = new ArrayList<>();
actual.add(user);
actual.add(user1);
//actual.add(user2);
//run the test if the list expected and actual are not equal
//the test will fail, read the test results in the console
Assert.assertEquals(expected, actual);
}
我們執行測試並看到以下內容: 現在我們可以看一下測試失敗的原因。在這裡我們看到檢查清單中的使用者比目前清單中的使用者多。這就是失敗的原因。我們可以在 main 中檢查一下嗎?JUnit : main = 1 : 0。讓我們看看如果測試包含完全不同的對象,測試會是什麼樣子,讓我們這樣做:
@Test
public void getAllUsers() {
// create test data
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
//create an expected list and fill it with the data of our method
List<User> expected = User.getAllUsers();
//create actual list put data in it for comparison
//what we expect the method to return
List<User> actual = new ArrayList<>();
actual.add(new User("User1", 1, Sex.MALE));
actual.add(new User("User2", 2, Sex.FEMALE));
actual.add(new User("User3", 3, Sex.MALE));
//run the test if the list expected and actual are not equal
//the test will fail, read the test results in the console
Assert.assertEquals(expected, actual);
}
這就是控制台中將出現的內容: 在這裡您可以立即看到比較列表中有不同的用戶,我們也可以單擊&ltClick to see Difference>我們將獲得一個窗口,在其中我們可以詳細查看我們有哪些數據問題與. IDEA將突出顯示所有存在差異的領域。 main
這會發生嗎?- 不。getAllUsers()
JUnit : main = 2 : 0 好吧,讓我們繼續,我們還有一堆方法需要測試),但是等等,檢查方法是否會返回給我們也不錯,因為那是我們如何處理驗證器捕獲的JavaRushnull
任務) 。就這樣吧,三戈比的事…
@Test
public void getAllUsers_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers();
Assert.assertNotNull(expected);
}
是的,是的,驗證器大致就是這樣捕獲我們的null
;)現在讓我們執行這個測試,看看它向我們展示了什麼。而且會顯示錯誤,怎麼辦???這裡怎麼會出現測試錯誤))) 在這裡我們可以收穫用測試覆蓋我們的程式碼的第一個成果。你還記得,allUsers
我們在建構函式中初始化了該字段,這意味著在呼叫該方法時getAllUsers()
,我們將引用一個尚未初始化的物件。讓我們編輯它,從建構函數中刪除初始化,並在聲明欄位時執行此操作。
private static Map<Integer, User> allUsers = new HashMap<>();
public User(String name, int age, Sex sex) {
this.name = name;
this.age = age;
this.sex = sex;
if (!hasUser()) {
countId++;
this.id = countId;
allUsers.put(id, this);
}
}
讓我們運行測試,現在一切都很好。 我認為在 main 中捕獲 NPE 並不容易,我想你會同意計數是 JUnit: main = 3: 0 然後我將用測試覆蓋所有方法,讓你看看它會是什麼樣子...現在我們的測試類別如下圖所示:
package user;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class UserTest {
@Test
public void getAllUsers() {
// create test data
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
//create an expected list and fill it with the data of our method
List<User> expected = User.getAllUsers();
//create actual list put data in it for comparison
//what we expect the method to return
List<User> actual = new ArrayList<>();
actual.add(user);
actual.add(user1);
actual.add(user2);
//run the test if the list expected and actual are not equal
//the test will fail, read the test results in the console
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers();
Assert.assertNotNull(expected);
}
@Test
public void getAllUsers_MALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
List<User> expected = User.getAllUsers(Sex.MALE);
List<User> actual = new ArrayList<>();
actual.add(user);
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_MALE_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers(Sex.MALE);
Assert.assertNotNull(expected);
}
@Test
public void getAllUsers_FEMALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
List<User> expected = User.getAllUsers(Sex.FEMALE);
List<User> actual = new ArrayList<>();
actual.add(user1);
actual.add(user2);
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_FEMALE_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers(Sex.FEMALE);
Assert.assertNotNull(expected);
}
@Test
public void getHowManyUsers() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getHowManyUsers();
int actual = 3;
Assert.assertEquals(expected, actual);
}
@Test
public void getHowManyUsers_MALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getHowManyUsers(Sex.MALE);
int actual = 1;
Assert.assertEquals(expected, actual);
}
@Test
public void getHowManyUsers_FEMALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getHowManyUsers(Sex.FEMALE);
int actual = 2;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getAllAgeUsers();
int actual = 35 + 34 + 7;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers_MALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getAllAgeUsers(Sex.MALE);
int actual = 35;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers_FEMALE() {
User user = new User("Eugene", 35, Sex.MALE);
User user1 = new User("Marina", 34, Sex.FEMALE);
User user2 = new User("Alina", 7, Sex.FEMALE);
int expected = User.getAllAgeUsers(Sex.FEMALE);
int actual = 34 + 7;
Assert.assertEquals(expected, actual);
}
}
是的,事實證明它並不小,但是在處理大型專案時會發生什麼。這裡可以減少什麼?在評估完所有內容之後,您可以看到我們在每個測試中創建了測試數據,並且這裡註釋可以幫助我們。我們假設 @Before
- 該註釋@Before
表明該方法將在每個被測試的方法之前執行@Test
。這就是我們現在有註解的測試類別的樣子@Before
:
package user;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class UserTest {
private User user;
private User user1;
private User user2;
@Before
public void setUp() throws Exception {
user = new User("Eugene", 35, Sex.MALE);
user1 = new User("Marina", 34, Sex.FEMALE);
user2 = new User("Alina", 7, Sex.FEMALE);
}
@Test
public void getAllUsers() {
List<User> expected = User.getAllUsers();
List<User> actual = new ArrayList<>();
actual.add(user);
actual.add(user1);
actual.add(user2);
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_NO_NULL() {
List<User> expected = User.getAllUsers();
Assert.assertNotNull(expected);
}
@Test
public void getAllUsers_MALE() {
List<User> expected = User.getAllUsers(Sex.MALE);
List<User> actual = new ArrayList<>();
actual.add(user);
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_MALE_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers(Sex.MALE);
Assert.assertNotNull(expected);
}
@Test
public void getAllUsers_FEMALE() {
List<User> expected = User.getAllUsers(Sex.FEMALE);
List<User> actual = new ArrayList<>();
actual.add(user1);
actual.add(user2);
Assert.assertEquals(expected, actual);
}
@Test
public void getAllUsers_FEMALE_NO_NULL() {
//add check for null
List<User> expected = User.getAllUsers(Sex.FEMALE);
Assert.assertNotNull(expected);
}
@Test
public void getHowManyUsers() {
int expected = User.getHowManyUsers();
int actual = 3;
Assert.assertEquals(expected, actual);
}
@Test
public void getHowManyUsers_MALE() {
int expected = User.getHowManyUsers(Sex.MALE);
int actual = 1;
Assert.assertEquals(expected, actual);
}
@Test
public void getHowManyUsers_FEMALE() {
int expected = User.getHowManyUsers(Sex.FEMALE);
int actual = 2;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers() {
int expected = User.getAllAgeUsers();
int actual = 35 + 34 + 7;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers_MALE() {
int expected = User.getAllAgeUsers(Sex.MALE);
int actual = 35;
Assert.assertEquals(expected, actual);
}
@Test
public void getAllAgeUsers_FEMALE() {
int expected = User.getAllAgeUsers(Sex.FEMALE);
int actual = 34 + 7;
Assert.assertEquals(expected, actual);
}
}
好吧,你呢,它已經更有趣、更容易閱讀了;)這是 JUnit 註釋的清單;使用它們肯定更容易。
@Test – определяет что метод method() является тестовым.
@Before – указывает на то, что метод будет выполнятся перед каждым тестируемым методом @Test.
@After – указывает на то что метод будет выполнятся после каждого тестируемого метода @Test
@BeforeClass – указывает на то, что метод будет выполнятся в начале всех тестов,
а точней в момент запуска тестов(перед всеми тестами @Test).
@AfterClass – указывает на то, что метод будет выполнятся после всех тестов.
@Ignore – говорит, что метод будет проигнорирован в момент проведения тестирования.
(expected = Exception.class) – указывает на то, что в данном тестовом методе
вы преднамеренно ожидаете Exception.
(timeout = 100) – указывает, что тестируемый метод не должен занимать больше чем 100 миллисекунд.
用於檢查的主要類別方法Assert
:
fail(String) – указывает на то что бы тестовый метод завалился при этом выводя текстовое сообщение.
assertTrue([message], boolean condition) – проверяет, что логическое condition истинно.
assertsEquals([String message], expected, actual) – проверяет, что два значения совпадают.
Примечание: для массивов проверяются ссылки, а не содержание массивов.
assertNull([message], object) – проверяет, что an object является пустым null.
assertNotNull([message], object) – проверяет, что an object не является пустым null.
assertSame([String], expected, actual) – проверяет, что обе переменные относятся к одному an objectу.
assertNotSame([String], expected, actual) – проверяет, что обе переменные относятся к разным an objectм.
這就是我們如何在 Maven 中新增 JUnit 4.12 依賴項
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
此處繼續 -> JUnit 第二部分
GO TO FULL VERSION