@@ -35,69 +35,45 @@ expected when changes are made.
35
35
Automated tests don't fully replace manually testing your smart contract but
36
36
it's an important tool to ensuring your contract will work as expected.
37
37
38
- ## Let's add some tests
38
+ ## Let's Get Started
39
39
40
- ### First configure hardhat for testing
40
+ ### Setting up our project dependencies
41
41
42
- <ContentCallout emoji = " 💡" size = " md" variant = " info" >
43
- We'll depend on ` hardhat ` as our project framework and will use its testing
44
- features. Your project is already hardhat-based so you should be all set to
45
- continue. However if you're unsure on how to setup the initial hardhat
46
- project, refer to Lesson 2 and search for ` npx hardhat ` in the "Create your
47
- project" section.
48
- </ContentCallout >
49
-
50
- Add a line in your ` scripts ` section of ` package.json ` so it looks like this
51
- below. You may already have other scripts' lines so don't get rid of those.
52
-
53
- ``` javascript
54
- " scripts" : {
55
- " test" : " hardhat test --network hardhat"
56
- },
57
- ```
58
-
59
- Next create a ` test ` folder in the root of your project, and add a new file
60
- called ` tier-nft.test.js ` with these lines:
42
+ If you have an existing project from your previous work on the TierNFT lesson,
43
+ you have all the Hardhat dependencies installed.
61
44
62
- ``` javascript
63
- const { expect } = require ( ' chai ' )
45
+ Otherwise let's create a new Hardhat project and copy in the contract which
46
+ we'll be testing.
64
47
65
- describe (' TierNFT' , function () {
66
- it (' placeholder test' )
67
- })
68
- ```
48
+ To create a new project, please refer to _ Lesson 3 - Tier NFTs_ and search for
49
+ the “First things first 👷♂️" section to get your project going. Follow the steps
50
+ until "Let’s start coding”, then open up your code editor.
69
51
70
- <ContentCallout emoji = " 💡" size = " md" variant = " info" >
71
- ` expect() ` from the Chai library is used to test various conditions. There are
72
- many examples in this lesson.
73
- </ContentCallout >
52
+ _ If you are using VSCode, type ` code . ` in your terminal to open VSCode._
74
53
75
- Now with a test file and a command to run the tests, try ` npm test ` and you
76
- should see:
54
+ After running through that section you'll have a working Hardhat project for the
55
+ next steps.
77
56
78
- ``` bash
79
- TierNFT
80
- - placeholder test
57
+ ### Add test command for running tests
81
58
59
+ Add a line in your ` scripts ` section of ` package.json ` so it looks like this
60
+ below. You may already have other scripts' lines so don't get rid of those. If
61
+ you already have a ` "test" ` script line, make sure it now has
62
+ ` hardhat test --network hardhat ` . If you have multiple script lines make sure
63
+ the last line does not have a comma at the end, otherwise you'll see an error.
82
64
83
- 0 passing (5ms)
84
- 1 pending
65
+ ``` javascript
66
+ " scripts" : {
67
+ " something" : " some other script" ,
68
+ " test" : " hardhat test --network hardhat"
69
+ },
85
70
```
86
71
87
- This now proves:
88
-
89
- - hardhat is running ok
90
- - the tests are found and are running
72
+ ### Bring in the contract we'll be testing
91
73
92
- ` pending ` means we haven't added the real test yet, so it is neither passing nor
93
- failing. Adding ` pending ` placeholders are a good way to brainstorm and remind
94
- yourself what tests you need to write.
95
-
96
- ## What do we want to test on our TierNFT contract?
97
-
98
- Now that the tools are set up, what should we test?
99
-
100
- Let's look at our contract from Lesson 3:
74
+ If you don't already have ` TierNFT.sol ` in your project from Lesson 3, below is
75
+ that same contract. Please create a new file called ` TierNFT.sol ` in a
76
+ ` contracts ` folder in the root of the project, and copy in this code:
101
77
102
78
``` solidity
103
79
// SPDX-License-Identifier: MIT
@@ -198,6 +174,32 @@ contract TierNFT is ERC721, Ownable {
198
174
}
199
175
```
200
176
177
+ ### Verify Solidity Version
178
+
179
+ One small, but crucial change before we proceed. Ensure the version of Solidity
180
+ being used to run the contract is the same one configured in
181
+ ` hardhat.config.js ` .
182
+
183
+ Copy the Solidity version from the ` pragma ` statement at the top of your
184
+ contract, to the ` hardhat.config.js ` file and replace that ` solidity: "version" `
185
+ with that of your contract.
186
+
187
+ For example, since our contract is using Solidity ` 0.8.12 ` :
188
+
189
+ ```
190
+ require("@nomicfoundation/hardhat-toolbox");
191
+ require('dotenv').config();
192
+
193
+ module.exports = {
194
+ solidity: "0.8.12",
195
+ };
196
+ ```
197
+
198
+ ## What do we want to test on our TierNFT contract?
199
+
200
+ Now that the tools are set up, let's talk about what we want to test in our
201
+ smart contract. We'll then create the tests.
202
+
201
203
What is the contract trying to do?
202
204
203
205
- it accepts payment and mints NFTs
@@ -212,6 +214,12 @@ We want to test that those functions work in a variety of cases.
212
214
For example, we can test that a mint happens when enough Eth is spent and that a
213
215
mint fails if there is not enough Eth spent.
214
216
217
+ ### Creating our test file
218
+
219
+ If you don't have one already, create a ` test ` folder in the root of your
220
+ project, and add a new file called ` tier-nft.test.js ` which will hold our new
221
+ test code.
222
+
215
223
### Start testing constructor(), mint() and withdraw()
216
224
217
225
Let's start with testing the ` constructor ` and making sure we can set and
@@ -220,6 +228,8 @@ retrieve the NFT name and symbol.
220
228
In addition to these first two tests we'll add setup code that we'll reuse for
221
229
all the other tests too.
222
230
231
+ Please add the following code to your new ` tier-nft.test.js ` file:
232
+
223
233
``` javascript
224
234
const { expect } = require (' chai' )
225
235
@@ -257,6 +267,20 @@ describe('TierNFT', function () {
257
267
})
258
268
```
259
269
270
+ <ContentCallout emoji = " 💡" size = " md" variant = " info" >
271
+ Before we walk through, let's make sure everything is working correctly. Run
272
+ the tests using ` npm test ` and you should see these two initial tests pass.
273
+ ** This is an important milestone! You created your first tests and they now
274
+ pass.**
275
+ </ContentCallout >
276
+
277
+ Now let's walk through the test code we've pasted in and explain what it does.
278
+
279
+ <ContentCallout emoji = " 💡" size = " md" variant = " info" >
280
+ ` expect() ` from the Chai library is used to test various conditions. There are
281
+ many examples in this lesson.
282
+ </ContentCallout >
283
+
260
284
At the top we see constants with the name and symbol of the NFT collection:
261
285
262
286
``` javascript
@@ -370,7 +394,39 @@ failure looks like:
370
394
371
395
### Let's add tests for mint()
372
396
373
- Here are tests we'll be adding:
397
+ Now is time to add tests for our ` mint() ` method. We'll group these new tests
398
+ into a new ` describe ` section.
399
+
400
+ Where exactly do we add this ` describe ` block?
401
+
402
+ Currently the end of our ` tier-nft.test.js ` looks like this, with just one
403
+ additional comment line I added that says
404
+ ` // this is where existing describe section ends ` :
405
+
406
+ ``` javascript
407
+ describe (' constructor' , async () => {
408
+ it (' set proper collection name' , async function () {
409
+ const name = await contract .name ()
410
+ expect (name).to .equal (' TierNFT' )
411
+ })
412
+
413
+ it (' set proper collection symbol' , async function () {
414
+ const symbol = await contract .symbol ()
415
+ expect (symbol).to .equal (' Tier' )
416
+ })
417
+ })
418
+ // this is where existing describe section ends
419
+ })
420
+ ```
421
+
422
+ Our new ` describe ` section show below will replace that line that says
423
+ ` // this is where existing describe section ends ` .
424
+
425
+ <ContentCallout emoji = " 💡" size = " md" variant = " info" >
426
+ Make sure you keep that last line ` }) ` which is the very end of the block of
427
+ code that holds ** all** of the ` describe ` blocks you're adding in this whole
428
+ lesson.
429
+ </ContentCallout >
374
430
375
431
``` javascript
376
432
describe (' mint' , async () => {
@@ -413,6 +469,10 @@ describe('mint', async () => {
413
469
})
414
470
```
415
471
472
+ <ContentCallout emoji = " 💡" size = " md" variant = " info" >
473
+ Run the tests using ` npm test `
474
+ </ContentCallout >
475
+
416
476
These tests introduce additional code that are helpful when testing contracts.
417
477
418
478
With minting, one needs to pay the right price, we should also see the total
@@ -424,20 +484,19 @@ occurs. If not enough Eth is sent, the contract fails with an error and the
424
484
transaction is reverted as if nothing happened.
425
485
426
486
In this first test we want to ensure our method call is properly reverted when
427
- the proper amount of Eth is not provided. This happens in the
428
- ` await expect().to.be.revertedWith('Not enough value for the minimum Tier') `
429
- line. _ The code calling the contract has been temporarily removed to highlight
430
- what's happening._ We're expecting the call to be reverted when not sending
431
- enough payment, along with a specific error message from the contract.
432
-
433
- And the method inside that ` expect() ` method looks like this:
487
+ the proper amount of Eth is not provided. This happens here:
434
488
435
489
``` javascript
436
- contract .mint ({
437
- value: hre .ethers .utils .parseEther (' 0.001' ),
438
- })
490
+ await expect (
491
+ contract .mint ({
492
+ value: hre .ethers .utils .parseEther (' 0.001' ),
493
+ }),
494
+ ).to .be .revertedWith (' Not enough value for the minimum Tier' )
439
495
```
440
496
497
+ We're expecting the call to be reverted when not sending enough payment, along
498
+ with a specific error message from the contract.
499
+
441
500
Here we're just calling ` mint() ` with a parameter that sets the amount of Eth we
442
501
want to send. In this case ` 0.001 ` Eth is less than our contract minimum of
443
502
` 0.01 ` Eth so this correctly fails. Our test confirms this.
@@ -487,6 +546,10 @@ describe('withdrawal', async () => {
487
546
})
488
547
```
489
548
549
+ <ContentCallout emoji = " 💡" size = " md" variant = " info" >
550
+ Run the tests using ` npm test `
551
+ </ContentCallout >
552
+
490
553
You'll see similar patterns from the previous ` mint() ` tests. Here are a couple
491
554
of additional highlights:
492
555
@@ -777,6 +840,10 @@ describe('tokenURI and helpers', async () => {
777
840
})
778
841
```
779
842
843
+ <ContentCallout emoji = " 💡" size = " md" variant = " info" >
844
+ Run the tests using ` npm test `
845
+ </ContentCallout >
846
+
780
847
The final test is an example mentioned earlier about adding a test before
781
848
refactoring with helper methods. It checks that the initial ` tokenURI() ` method
782
849
(which returns an encoded Base64 string) returns the right result. It's helpful
0 commit comments