HIT-软件构造 | Lab1 项目配置
⚠️ 警告:
本文所述内容仅能帮助你在 JetBrains IDEA 下以不修改代码框架中任何 package
命名的方式,优雅地完成实验内容,但注意到 实验指导-Lab0-3.3.4
中所述:
这意味着完成实验后需要将基于 Eclipse / IDEA 的项目转换成某一通用的构建系统描述的项目,以应对 TA 可能采取的自动编译评测方式。
如果你已经熟悉 IDEA 的基本使用,本文后半部分会讲述如何将 IDEA 普通 Java 项目迁移至使用 Gradle 构建,可直接转跳阅读 ➡️
HIT-CS32123 软件构造课程 Lab1 项目结构大致如图:
1 | .Lab1 |
从拿到的框架可知 P2
是一个 Eclipse 项目,而众所周知,JetBrains IDEA 比 Eclipse 好用到不知道哪里去了。因此本文将介绍如何在 IDEA 中正确配置本次实验的项目结构。
先决条件
以下先决条件在此不再赘述:
- 配置 JDK (版本要求大于 )
- 下载并安装 JetBrains IDEA (本文使用的是旗舰版,社区版与旗舰版的配置过程只有细微差别)
解决方案
新建项目
只需要注意项目类型选 Java 。
另外 JDK版本只需要大于课程要求的 就行,其他的无所谓,因为稍后我们将通过 IDE 里的设置将代码所用特性限制在 Java 11 之前。
配置 P1
刚建好的项目如图所示,可以看见 src
下面什么都没有:
我们将下载到的代码框架的 P1
与 P2
文件夹直接复制到 src
下,此处你可以直接用文件资源管理器进行该操作。注意,不建议把 Spring2022_HITCS_SC_Lab1
这个项目 clone
下来,尤其不建议直接 clone
到 src
里,而只需要下载就可以。完成后如图所示:
可以发现此时 IDEA 将 P1
和 P2
识别为 Java 包,但这是不对的,因为从 P2
的 RulesOf6005.java
看, P1
, P2
包括之后的 P3
更像是可以独立编译运行的 Java 项目。 rules
应该是以 P2
作为顶层目录下的一个 package
而不是像现在这样 IDE 认为它应该被修改为包 P2.rules
。
为了解决这个问题,按下 Ctrl+Shift+Alt+S
来打开 Project Structure
,这是 IDEA 项目中一个非常重要的面板,你可以在这里利用 IDE 管理你的项目,比如你可以在左侧的 Project
里设置这个项目的语言等级(language level),比 JDK 版本(演示机上设置的是JDK 17)低的任何等级都可以被设置,在本次实验中我们允许使用 Java 8 - 11。但现在我们选择左侧的 Module
:
在继续之前,我们先引入 IDEA 中 Module 的概念,它不是从 Java 9 开始支持的那个 Java 中的 Module ,但有几分相似,事实上 IDEA 中一个项目被称为 Project , Project 下允许构建可以独立运行的子组件,并设置其间的依赖关系,称为 Module 。IDEA 还有许多概念与 Eclipse 中的一些概念存在对应关系:
理解上述概念后,我们知道,解决上述问题的一个方法是:实验所需要的 P1
、 P2
和 P3
在 IDEA 中应该以 Module 的形式存在。接下来我们将为 P1
和 P2
创建 Module。
点击上方的 +
号,选择 New Module
,和创建项目的窗口非常类似,我们再次选择 Java :
而路径则需要选择这个项目下的 src/P1
:
此处表明一个 Module 确实像是一个新的 IDEA Java 项目,它为我们开发 Java 程序提供了一个独立的空间。
完成之后点击 OK
便回到了我们的 Project Structure
面板,在点击 OK
完成创建 P1
模块之前,先点击上方的 Sources
来到下面这个面板:
根据实验要求,我们 MagicSquare.java
应处于 P1
的根目录而不是 P1
的 src
子目录下,因此需要选择 src
,然后将上方的 Sources
按钮取消选中,之后你甚至可以直接删除 P1
下的这一个 src
文件夹;最后选择 P1
根目录本身,选中 Sources
将其作为 P1
模块的 Sources Root
。
点击 OK
后我们便完成了 P1
模块的创建。可以看见 P1
的图标发生了明显变化,它现在不再是一个 package
而是一个可以独立编译运行的 Module
!
另外根据实验指导,我们需要在 P1
下创建一个 txt
子目录来存放所有 1.txt
到 5.txt
,注意在一个 Source Root
下,创建一个 package
等同于创建一个文件夹,所以我们可以通过在 P1
下创建一个名为 txt
的包来创建 txt
这个目录。
至此我们完成了 P1
模块的创建,你甚至可以写一个 Hello World!
程序来测试一下。
配置 P2
| JUnit
配置
P2
与 P1
的不同之处在于它提供了一个代码框架,同时它还依赖于 JUnit
。 P2
配置的前半部分与 P1
完全相同,为了检验是否理解了 IDEA Module 的概念,作为练习,请读者自行为 P2
创建 Module 。完成后结果如图所示:
但是注意到此时项目还是有警告的,因为我们还没有配置 JUnit
,事实上这并不是一种良好的项目结构,测试类通常不应该与源码在同一模块下。但是在 IDEA 下完成 JUnit
配置十分容易,我们只需要打开 RulesOf6005Test.java
,将鼠标悬停在有红线的 junit
上,出现的提示中选择 Add 'JUnit' to classpath
,
在弹出的窗口中选 OK
,IDEA 将自动为我们下载 JUnit
包,然后将其添加到 P2
模块的依赖项中。
稍等片刻,所有警告都会消失, Project Structure
的 Dependencis
面板也显示 JUnit
确实被添加到了 P2
的依赖项列表里。
点击 RulesOf6005Test
里 testMayUseCodeInAssignment
右侧的小三角形,然后 Run
之,可以运行这一项单元测试。虽然出错了,但是可以看见 testMayUseCodeInAssignment
是可以运行的,只是 RulesOf6005.mayUseCodeInAssignment
还没有实现而已,所以报错,但这表明我们的对 P2
的配置已经完成了。
配置 P3
| 模块间的依赖关系
P3
是一个面向对象编程的练习,也是一个体验单元测试流程的练习。我们先来回顾一下实验指导要求的目录结构:
1 | .Lab1 |
和 P1
P2
一样,我们将 P3
和 test
里的 P3
都视作模块,唯一不同的是,test
里的 P3
是专门用来测试 src
里的 P3
的模块,因此虽然它的目录是 test/P3
但是个人认为给模块命名时称之为 P3Test
比较好,像这样:
其他步骤不再赘述,最终效果如图所示:
按照实验要求,我们需要先在 P3
中实现 FriendshipGraph
和 Person
类的功能,然后在 src/P3
( P3Test
与此意思相同,后文将不再区分)的 FriendshipGraphTest
类中对其进行测试。
为了演示这点而不违反 Collaboration policy
,本文将在 P3
创建 FriendshipGraph
类并在里面创建一个 public static int getInt(int x)
方法,这个方法传入一个 int
并返回这个 int
本身,非常无聊,但有助于演示;然后在 P3Test
中创建一个 FriendshipGraphTest
类,其中的 public void friendshipGraphGetIntTest()
方法用于测试 FriendshipGraph.getInt
方法:
此处是本节的重点,形如 assertEquals(0, FriendshipGraph.getInt(1))
便可以用于测试。因为在 FriendshipGraphTest
类的 friendshipGraphGetIntTest
方法中,我们既使用了 JUnit
库的方法 assertEquals
,又使用了 FriendshipGraph
中的方法,所以我们称 “FriendshipGraphTest
依赖于 JUnit
和 FriendshipGraph
” ;因为 FriendshipGraphTest
在 P3Test
模块中, FriendshipGraph
在 P3
模块中,所以同理,我们称 “P3Test
模块依赖于 P3
模块” 。
按照 P2
介绍的方式,我们可以很容易地为 P3Test
引入 JUnit
单元测试库,在此作为练习,效果如图所示:
此时 JUnit
可以正常使用,但是 FriendshipGraph
标红表示此处不可用,因为我们还没有设置 P3Test
依赖于 P3
。可以看见一旦我们将鼠标悬在 FriendshipGraph
上方,智能的 IDEA 就会建议我们将 P3
添加为依赖项。IDEA 给出这个正确的建议的原因之一是当前项目里只有 P3
里有 FriendshipGraph
类,具有特殊性,所以我们还是来看一下如何将一个模块设置为另一个模块的依赖项。
首先还是打开 Project Structure
,然后 选择 P3Test
模块,打开 Dependencies
面板,点击 +
号,选择 Module Dependency
:
在弹出的窗口中选择 P3
:
点击 OK
,可以看见我们成功将 P3
模块添加到 P3Test
的依赖项列表:
到此为止,我们已经完成了本次实验在 IDEA 中的全部配置。运行一下 FriendshipGraphTest
中的单元测试发现可以正确运行:
后续步骤
迁移至 Gradle
进行构建
正如前文所述,如果 TA 使用自动化测试,那么提交的项目应该与 IDE 无关。此处我们推荐使用 Gradle 管理项目。过程如下:
-
将下列依赖项放至项目根目录下
lib
文件夹内:junit-4.13.1.jar
hamcrest-core-1.31.jar
hamcrest-core-1.3-sources.jar
-
在项目根目录下新建
settings.gradle.kts
,填写内容如下:1
rootProject.name = "项目名"
-
在项目根目录下新建
build.gradle.kts
,详细配置请参考奆佬 Nullptr 的 [软构] 记一次 Gradle 的坑 -
接着点击
Link Gradle project
,等待 IDEA 完成 Gradle 项目初始化。
完成这一切后你可能发现 Project Structure
中 P1
等模块被重复了两次,这是因为 Gradle
将这些模块视作 Resource
并创建在根模块下。你可以删掉其中不在项目根模块中的那一个,因为它们原本是由 IDEA 管理的,现在不需要了。