#include <bits/stdc++.h>
using namespace std;
struct Edge {
  int u, v;
  bool forward, disabled, explr;
  int from(int pos) {
    if (pos == u) return v;
    return u;
  }
};
struct Graph {
  vector<Edge> edge;
  vector<vector<Edge*> > conn;
  int n;
  vector<bool> even;
  Graph(int nsize) {
    n = nsize;
    even.resize(n, true);
  }
  void addEdge(int a, int b) {
    edge.push_back({a, b, false, false, false});
    even[a] = !even[a];
    even[b] = !even[b];
  }
  void init() {
    conn.resize(n);
    for (auto& c : edge) {
      conn[c.u].push_back(&c);
      conn[c.v].push_back(&c);
      if (!even[c.u] || !even[c.v]) c.disabled = true;
    }
  }
  int cycleRemove_dfs(int pos, vector<bool>& curexplr, vector<int>& edgeIndex) {
    if (curexplr[pos]) return pos;
    curexplr[pos] = true;
    int& i = edgeIndex[pos];
    while (i < (int)conn[pos].size()) {
      Edge* ep = conn[pos][i++];
      if (!ep->disabled && !ep->explr) {
        ep->explr = true;
        int ret = cycleRemove_dfs(ep->from(pos), curexplr, edgeIndex);
        if (ret != -1) {
          ep->disabled = true;
          if (ep->u == pos) ep->forward = true;
          if (ret != pos) {
            curexplr[pos] = false;
            return ret;
          }
        }
      }
    }
    curexplr[pos] = false;
    return -1;
  }
  void cycleRemove() {
    vector<bool> curexplr(n, false);
    vector<int> edgeIndex(n, 0);
    for (int i = 0; i < n; i++) cycleRemove_dfs(i, curexplr, edgeIndex);
    for (auto& ce : edge) ce.explr = false;
  }
  vector<int> outSum;
  void applyEdge(Edge* ep) {
    if (ep->forward) {
      outSum[ep->u]++;
      outSum[ep->v]--;
    } else {
      outSum[ep->v]++;
      outSum[ep->u]--;
    }
  }
  void deForest_dfs(int pos, vector<int>& edgeIndex) {
    int& i = edgeIndex[pos];
    while (i < (int)conn[pos].size()) {
      Edge* ep = conn[pos][i++];
      if (!ep->disabled) {
        ep->disabled = true;
        if (ep->u == pos) ep->forward = true;
        if (outSum[pos] == 1) ep->forward = !ep->forward;
        applyEdge(ep);
        deForest_dfs(ep->from(pos), edgeIndex);
      }
    }
  }
  void deForest() {
    outSum.resize(n, false);
    vector<int> edgeIndex(n, 0);
    for (int i = 0; i < n; i++) deForest_dfs(i, edgeIndex);
    for (auto& ce : edge) ce.explr = false;
  }
  void resolve() {
    for (auto& e : edge) {
      if (even[e.u] && !even[e.v]) {
        if (outSum[e.u] < 1) e.forward = true;
        applyEdge(&e);
      } else if (!even[e.u] && even[e.v]) {
        if (outSum[e.v] == 1) e.forward = true;
        applyEdge(&e);
      }
    }
  }
};
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  int T;
  cin >> T;
  for (int tcase = 0; tcase < T; tcase++) {
    int n, m;
    cin >> n >> m;
    Graph g(n);
    for (int i = 0; i < m; i++) {
      int a, b;
      cin >> a >> b;
      g.addEdge(a - 1, b - 1);
    }
    g.init();
    g.cycleRemove();
    g.deForest();
    g.resolve();
    int result = 0;
    for (int i = 0; i < n; i++)
      if (g.even[i]) result++;
    cout << result << '\n';
    for (auto& e : g.edge) {
      if (e.forward)
        cout << e.u + 1 << ' ' << e.v + 1 << '\n';
      else
        cout << e.v + 1 << ' ' << e.u + 1 << '\n';
    }
  }
  return 0;
}
