Testing
Learn how to write tests for your Dart code using the `package:test` library.
In this chapter, you'll learn how to write tests for your Dart code. Testing is
crucial for ensuring that your application behaves as expected and remains
stable as you make changes. You'll use the package:test library, a popular
testing framework for Dart, to write unit tests for the data models you created
in the previous chapter.
Prerequisites
#Before you begin this chapter, ensure you:
-
Have completed Chapter 9 and have a working Dart development environment with
the
dartpediaproject. - Are familiar with basic programming concepts like variables, functions, and control flow.
- Understand the purpose of testing in software development.
Tasks
#
In this chapter, you will add tests to the wikipedia package, ensuring that
the JSON deserialization logic for your data models is working correctly.
Task 1: Add the test dependency
#
First, you need to confirm that the test package is already a development
dependency in your project.
Open the
wikipedia/pubspec.yamlfile within your project.Locate the
dev_dependenciessection.-
Verify that
test: ^1.24.0(or the latest stable version) is present underdev_dependencies.yamldev_dependencies: lints: ^5.0.0 test: ^1.24.0If the
testdependency is missing, add it to yourpubspec.yamlfile. The^symbol allows compatible versions to be used. -
If you made any changes to the file, save
pubspec.yamland rundart pub getin your terminal from thewikipediadirectory. This command fetches any newly added dependencies and makes them available for use in your project.You should see output similar to this:
bashResolving dependencies... Downloading packages... + test 1.25.1 Changed 2 dependencies!
Task 2: Create a test file and add imports
#Next, create a test file for your data models and add the necessary imports to it.
Navigate to the
wikipedia/testdirectory.Create a new file named
model_test.dartin this directory.-
Open the
wikipedia/test/model_test.dartfile and add the followingimportstatements at the top of the file:dartimport 'dart:convert'; import 'dart:io'; import 'package:test/test.dart'; import 'package:wikipedia/src/model/article.dart'; import 'package:wikipedia/src/model/search_results.dart'; import 'package:wikipedia/src/model/summary.dart'; const String dartLangSummaryJson = './test/test_data/dart_lang_summary.json'; const String catExtractJson = './test/test_data/cat_extract.json'; const String openSearchResponse = './test/test_data/open_search_response.json';These lines import the
testpackage, which provides the testing framework, and the data model files you want to test. The constant strings declare the location of your sample data.
Task 3: Create the test data files
#
The tests you need to write rely on local JSON files that mimic the
responses from the Wikipedia API. You need to create a
test_data directory and populate it with three files.
Navigate to the
wikipedia/testdirectory.Create a new directory named
test_data.-
Inside the
test_datadirectory, create a new file nameddart_lang_summary.jsonand paste the following content into it:json{ "type": "standard", "title": "Dart (programming language)", "displaytitle": "<span class=\"mw-page-title-main\">Dart (programming language)</span>", "namespace": { "id": 0, "text": "" }, "wikibase_item": "Q406009", "titles": { "canonical": "Dart_(programming_language)", "normalized": "Dart (programming language)", "display": "<span class=\"mw-page-title-main\">Dart (programming language)</span>" }, "pageid": 33033735, "lang": "en", "dir": "ltr", "revision": "1259309990", "tid": "671bc7c6-aa67-11ef-aa2a-7c1da4fbe8fb", "timestamp": "2024-11-24T13:24:16Z", "description": "Programming language", "description_source": "local", "content_urls": { "desktop": { "page": "https://en.wikipedia.org/wiki/Dart_(programming_language)", "revisions": "https://en.wikipedia.org/wiki/Dart_(programming_language)?action=history", "edit": "https://en.wikipedia.org/wiki/Dart_(programming_language)?action=edit", "talk": "https://en.wikipedia.org/wiki/Talk:Dart_(programming_language)" }, "mobile": { "page": "https://en.m.wikipedia.org/wiki/Dart_(programming_language)", "revisions": "https://en.m.wikipedia.org/wiki/Special:History/Dart_(programming_language)", "edit": "https://en.m.wikipedia.org/wiki/Dart_(programming_language)?action=edit", "talk": "https://en.m.wikipedia.org/wiki/Talk:Dart_(programming_language)" } }, "extract": "Dart is a programming language designed by Lars Bak and Kasper Lund and developed by Google. It can be used to develop web and mobile apps as well as server and desktop applications.", "extract_html": "<p><b>Dart</b> is a programming language designed by Lars Bak and Kasper Lund and developed by Google. It can be used to develop web and mobile apps as well as server and desktop applications.</p>" } -
Next, create a file named
cat_extract.json. This file is very long, so copy the contents from this link: https://github.com/ericwindmill/dash_getting_started/blob/main/dart_step_by_step/step_10/wikipedia/test/test_data/cat_extract.json -
Next, create a file named
open_search_response.jsonand paste this content into it:json[ "dart", [ "Dart", "Darth Vader", "Dartmouth College", "Darts", "Darth Maul", "Dartford Crossing", "Dart (programming language)", "Dartmouth College fraternities and sororities", "Dartmoor", "Dartmouth, Massachusetts" ], [ "", "", "", "", "", "", "", "", "", "" ], [ "https://en.wikipedia.org/wiki/Dart", "https://en.wikipedia.org/wiki/Darth_Vader", "https://en.wikipedia.org/wiki/Dartmouth_College", "https://en.wikipedia.org/wiki/Darts", "https://en.wikipedia.org/wiki/Darth_Maul", "https://en.wikipedia.org/wiki/Dartford_Crossing", "https://en.wikipedia.org/wiki/Dart_(programming_language)", "https://en.wikipedia.org/wiki/Dartmouth_College_fraternities_and_sororities", "https://en.wikipedia.org/wiki/Dartmoor", "https://en.wikipedia.org/wiki/Dartmouth,_Massachusetts" ] ]
With these files in place, you're ready to write the tests that will verify your data models.
Task 4: Write tests for JSON deserialization
#
Now, you'll write tests for the JSON deserialization logic in your data models.
You'll use the group, test, and expect functions from the
test package.
-
Use the
groupfunction to group related tests together. Add the following to yourwikipedia/test/model_test.dartfile:dartvoid main() { group('deserialize example JSON responses from wikipedia API', () { // Tests will go here }); }The
groupfunction takes a description of the group and a callback function that contains the tests. -
Create a test for the
Summarymodel. Add the followingtestfunction inside thegroupfunction:dartvoid main() { group('deserialize example JSON responses from wikipedia API', () { test('deserialize Dart Programming Language page summary example data from ' 'json file into a Summary object', () async { final String pageSummaryInput = await File(dartLangSummaryJson).readAsString(); final Map<String, Object?> pageSummaryMap = jsonDecode(pageSummaryInput) as Map<String, Object?>; final Summary summary = Summary.fromJson(pageSummaryMap); expect(summary.titles.canonical, 'Dart_(programming_language)'); }); }); }This
testfunction does the following:- Reads the contents of the
dart_lang_summary.jsonfile. - Decodes the JSON string into a
Map<String, Object?>. - Creates a
Summaryobject from the map using theSummary.fromJsonconstructor. - Uses the
expectfunction to assert that thecanonicalproperty of thetitlesobject is equal to'Dart_(programming_language)'.
The
expectfunction takes a value and a matcher. The matcher is used to assert that the value meets certain criteria. In this case, theequalsmatcher is used to assert that the value is equal to a specific string. - Reads the contents of the
-
Create a test for the
Articlemodel. Add the followingtestfunction inside thegroupfunction, after the previous test:dartvoid main() { group('deserialize example JSON responses from wikipedia API', () { test('deserialize Dart Programming Language page summary example data from ' 'json file into a Summary object', () async { final String pageSummaryInput = await File(dartLangSummaryJson).readAsString(); final Map<String, Object?> pageSummaryMap = jsonDecode(pageSummaryInput) as Map<String, Object?>; final Summary summary = Summary.fromJson(pageSummaryMap); expect(summary.titles.canonical, 'Dart_(programming_language)'); }); test('deserialize Cat article example data from json file into ' 'an Article object', () async { final String articleJson = await File(catExtractJson).readAsString(); final Map<String, Object?> articleMap = jsonDecode(articleJson) as Map<String, Object?>; final Map<String, Object?> pagesMap = (articleMap['query'] as Map)['pages'] as Map<String, Object?>; // The 'pagesMap' contains a single key (e.g., '6678'). // We get the first (and only) value from that map. final Map<String, Object?> catArticleMap = pagesMap.values.first as Map<String, Object?>; final Article article = Article( title: catArticleMap['title'] as String, extract: catArticleMap['extract'] as String, ); expect(article.title.toLowerCase(), 'cat'); }); }); }This
testfunction does the following:- Reads the contents of the
cat_extract.jsonfile. - Decodes the JSON string into a
List<Object?>. - Creates the
Articleobject from the list using theArticle.listFromJsonconstructor. - Uses the
expectfunction to assert that thetitleproperty of the first article is equal to'cat'.
- Reads the contents of the
-
Create a test for the
SearchResultsmodel. Add the followingtestfunction inside thegroupfunction, after the previous test:dartvoid main() { group('deserialize example JSON responses from wikipedia API', () { test('deserialize Dart Programming Language page summary example data from ' 'json file into a Summary object', () async { final String pageSummaryInput = await File(dartLangSummaryJson).readAsString(); final Map<String, Object?> pageSummaryMap = jsonDecode(pageSummaryInput) as Map<String, Object?>; final Summary summary = Summary.fromJson(pageSummaryMap); expect(summary.titles.canonical, 'Dart_(programming_language)'); }); test('deserialize Cat article example data from json file into ' 'an Article object', () async { final String articleJson = await File(catExtractJson).readAsString(); final Map<String, Object?> articleMap = jsonDecode(articleJson) as Map<String, Object?>; final Map<String, Object?> pagesMap = (articleMap['query'] as Map)['pages'] as Map<String, Object?>; // The 'pagesMap' contains a single key (e.g., '6678'). // We get the first (and only) value from that map. final Map<String, Object?> catArticleMap = pagesMap.values.first as Map<String, Object?>; final Article article = Article( title: catArticleMap['title'] as String, extract: catArticleMap['extract'] as String, ); expect(article.title.toLowerCase(), 'cat'); }); test('deserialize Open Search results example data from json file ' 'into an SearchResults object', () async { final String resultsString = await File(openSearchResponse).readAsString(); final List<Object?> resultsAsList = jsonDecode(resultsString) as List<Object?>; final SearchResults results = SearchResults.fromJson(resultsAsList); expect(results.results.length, greaterThan(1)); }); }); }This
testfunction does the following:- Reads the contents of the
open_search_response.jsonfile. - Decodes the JSON string into a
List<Object?>. - Creates a
SearchResultsobject from the list using theSearchResults.fromJsonconstructor. - Uses the
expectfunction to assert that theresultslist has a length greater than1.
- Reads the contents of the
Task 5: Run the tests
#Now that you've written the tests, you can run them to verify that they pass.
Open your terminal and navigate to the
wikipediadirectory.-
Run the command
dart test.You should see output similar to this:
bash00:02 +4: All tests passed!This confirms that all three tests are passing.
Review
#In this chapter, you learned about:
- Installing the
package:testlibrary. - Writing tests using
group,test, andexpect. - Creating test files and organizing tests.
- Writing tests for JSON deserialization logic.
- Using matchers to assert that values meet certain criteria.
Quiz
#Check your understanding
1 / 3group, test, and expect in Dart's testing library?
-
grouporganizes related tests,testdefines individual test cases,expectasserts that values match expectations.That's right!
Groups contain tests, tests contain expectations. This hierarchy keeps your test suite organized and your assertions clear.
-
groupruns tests,testdefines assertions,expectorganizes output.Not quite.
The roles are mixed up here. Think about what each name suggests: "group" implies organization, "test" implies a test case.
-
groupandtestare interchangeable, andexpectruns them both.Not quite.
They're not interchangeable. Each serves a distinct purpose in structuring your test code.
-
expectmust be called beforetest, which must be called beforegroup.Not quite.
The nesting order is reversed in this answer. Think about which element is the container and which is contained.
expect(results.length, greaterThan(1)), what is greaterThan(1) called and what does it do?
-
A matcher. It describes the condition the actual value should satisfy.
That's right!
Matchers like
greaterThan,equals,contains, andisNulldescribe expected conditions. They make test assertions readable and provide helpful failure messages. -
A validator. It throws an exception if the value is wrong.
Not quite.
Close, but not quite. Matchers don't throw directly, they instead return a result that
expectuses to pass or fail the test. -
A comparator. It returns
trueorfalsefor sorting.Not quite.
Comparators are used for sorting collections. This serves a different purpose in the testing context.
-
A predicate. It filters the results before testing.
Not quite.
Predicates are typically used for filtering collections. In
expect, the second argument serves a different role than filtering.
await File(path).readAsString(). What do you need to add to the test function for this to work?
-
Mark the test callback as
async:test('...', () async { ... })That's right!
Just like regular Dart functions, test callbacks can be
async. The test framework automatically waits for the returnedFutureto complete. -
Wrap the file read in a
Future.sync()call.Not quite.
There's no
Future.sync()in Dart. Think about what you normally do when a function usesawait. -
Use
testAsyncinstead oftest.Not quite.
There's no
testAsyncfunction. The regulartestfunction can handle async operations with the right modification to its callback. -
Call
await Future.delayed(Duration.zero)first to enable async mode.Not quite.
No special initialization or delay is needed. The change you need is to the function signature, not its body.
Next lesson
#
In the next lesson, you'll implement the Wikipedia API calls in your
dartpedia application. You'll use the http package to fetch data from the
Wikipedia API and display it to the user.
Unless stated otherwise, the documentation on this site reflects Dart 3.10.3. Page last updated on 2025-12-21. View source or report an issue.