flutter-todo-list-tutorial icon indicating copy to clipboard operation
flutter-todo-list-tutorial copied to clipboard

Coverage

Open SimonLab opened this issue 5 years ago • 4 comments

The flutter test --coverage run the tests and create a coverage report in coverage/lcov.info file. However the coverage doesn't catch untested files which make it difficult to know the coverage for all the project. A solution is to create a dummy test which import all the dart files of the Flutter project. This force the coverage to be updated for the project scope.

  • [x] Create a bash script to generate the dummy test importing all the dart files
  • [x] Run the script in Github actions before running the flutter test --coverage command

see

  • https://stackoverflow.com/questions/54602840/how-can-i-generate-test-coverage-of-untested-files-on-my-flutter-tests
  • https://github.com/flutter/flutter/issues/27997

SimonLab avatar Jan 21 '21 11:01 SimonLab

We can now see untested file with codecov: https://codecov.io/gh/dwyl/flutter-todo-list-tutorial/pull/17/tree?path=lib

image

Adding tests now

SimonLab avatar Jan 21 '21 12:01 SimonLab

The following test is faillaing:

  test('save todolist in shared preferences', () {
    final todoList = TodoListModel();
    expect(todoList.tasks.length, 0);
    final task = TaskModel(text: "task 1");
    todoList.addTaks(task);
    todoList.saveTasksToSharedPrefs();
    final todoList2 =
          TodoListModel(); // Load todolist from shared preferences when instance is created
    expect(todoList2.tasks.length, 1); //failing
  });

When TodoListModel() is called it fetch the data from shared preferences. Getting this function is asynchronous so when the test is checking for existing task it fails. I'm looking at removing the async call from the todolist constructor, this should make it easier to test it directly.

SimonLab avatar Jan 22 '21 12:01 SimonLab

I've changed how the way a todolist is created. before the getTasksFromSharedPrefs() was called directly inside the constructor:

class TodoListModel extends ChangeNotifier {
  List<TaskModel> tasks = [];

  TodoListModel() {
    getTasksFromSharedPrefs();
  }

  Future<void> getTasksFromSharedPrefs() async {
    final prefs = await SharedPreferences.getInstance();
    final tasksJson = prefs.getString('tasks');
    final jsonListTasks = jsonDecode(tasksJson).cast<Map<String, dynamic>>();
    tasks = jsonListTasks.map<TaskModel>((m) => TaskModel.fromJson(m)).toList();
    notifyListeners();
  }
}

Now the getTasksFromSharedPrefs() is called before the ChangeNotifierProvider and we are using the value constructor:

  Widget build(BuildContext context) {
    final TodoListModel todoList = TodoListModel(); // instanciate the todolist, empty for now
    todoList.getTasksFromSharedPrefs();  //get the tasks saved
    return Scaffold(
        appBar: AppBar(
          title: Text('TodoList'),
        ),
        body: ChangeNotifierProvider.value( //use value to create
          value: todoList,
          child: TodoListWidget() ,)
    );
  }

Now we can create a new test to check the todolist is saved:

  test('save and get todolist in shared preferences', () async {
    // create and save a todolist
    final todoList = TodoListModel();
    final task = TaskModel(text: "task 1");
    final task2 = TaskModel(text: "task 2");
    todoList.addTaks(task);
    todoList.addTaks(task2);
    await todoList.saveTasksToSharedPrefs();

    // get tasks from shared preferences
    final todoList2 = TodoListModel();
    await todoList2.getTasksFromSharedPrefs();
    expect(todoList2.tasks.length, 2);
  });

SimonLab avatar Jan 22 '21 15:01 SimonLab

image

@LuchoTurtle I think this issue might help your quest. 💭 The answer is: when you authenticate with your GitHub Account on Codecov they should see that you have "owner" access to the @dwyl org and allow you to create anything you need to accomplish your task. 🤞

nelsonic avatar Nov 15 '22 15:11 nelsonic