#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10, inf = N;
vector<int> adj[N], vec, topo, comp;
bool ok = false, mark[N];
vector<int> ans;
int deg[N], dist[N], par[N], vis[N], n, m;
vector<vector<int> > tree;
int root;
void cleaner() {
  for (int i = 0; i < n; i++) {
    adj[i].clear();
    dist[i] = 0, par[i] = 0, deg[i] = 0, vis[i] = false, mark[i] = false;
    ;
  }
  ok = false;
  ans.clear(), topo.clear(), vec.clear(), tree.clear(), comp.clear();
  return;
}
void input() {
  cin >> n >> m;
  cleaner();
  for (int i = 0; i < m; i++) {
    int v, u;
    cin >> v >> u;
    v--, u--;
    adj[v].push_back(u), adj[u].push_back(v);
    deg[v]++, deg[u]++;
  }
  for (int i = 0; i < n; i++) sort(adj[i].begin(), adj[i].end());
}
void print() {
  ok = true;
  if (ans.empty() || ans.size() == n) {
    cout << "No\n";
    return;
  }
  cout << "Yes\n";
  for (int i = 0; i < ans.size(); i++) {
    mark[ans[i]] = true;
  }
  cout << n - (int)ans.size() << "\n";
  for (int i = 0; i < n; i++) {
    if (!mark[i]) cout << i + 1 << " ";
  }
  cout << "\n";
}
void mod3k_0() {
  for (int i = 0; i < n; i++) {
    if (deg[i] % 3 == 0) {
      ans.push_back(i);
      ok = true;
      print();
      return;
    }
  }
}
void bfs(int v, int rt = n) {
  fill(dist, dist + n, inf);
  queue<int> q;
  dist[v] = 0;
  dist[rt] = 0;
  q.push(v);
  while (!q.empty()) {
    v = q.front();
    q.pop();
    for (auto u : adj[v]) {
      if (dist[u] == inf) {
        par[u] = v;
        dist[u] = dist[v] + 1;
        q.push(u);
      }
    }
  }
}
void dfs(int v, int p = -1) {
  dist[v] = topo.size();
  comp.push_back(v), topo.push_back(v);
  vis[v] = true;
  int len = n;
  for (auto u : adj[v]) {
    if (deg[u] % 3 == 2) {
      if (u == p || !vis[u]) continue;
      if (dist[u] < dist[v] && (len == n || dist[u] > dist[len])) len = u;
    }
  }
  if (len < n) {
    for (int i = dist[len]; i < topo.size(); i++) ans.push_back(topo[i]);
    print();
    return;
  } else {
    for (auto u : adj[v]) {
      if (u == p) continue;
      if (deg[u] % 3 == 2 && !vis[u]) {
        dfs(u, v);
        if (ok) return;
      }
    }
  }
  topo.pop_back();
}
void p121() {
  for (int i = 0; i < n; i++) {
    int len = n;
    if (deg[i] % 3 == 1) {
      bfs(i);
      for (int j = i + 1; j < n; j++) {
        if (deg[j] % 3 == 1 && (len == n || dist[j] < dist[len])) len = j;
      }
    }
    if (len != n) {
      ans.push_back(len);
      while (i != len) ans.push_back(par[len]), len = par[len];
      print();
      return;
    }
  }
}
void lca(vector<int> p) {
  fill(mark, mark + n, false);
  int rt = p[0], v = p[1];
  bfs(rt, root);
  for (auto u : p)
    if (dist[u] && dist[u] < dist[v]) v = u;
  ans.push_back(v);
  while (v != rt) ans.push_back(v = par[v]);
}
void solve() {
  input();
  if (n <= 3) {
    print();
    return;
  }
  if (ok) return;
  mod3k_0();
  if (ok) return;
  p121();
  if (ok) return;
  fill(dist, dist + n, 0);
  for (int i = 0; i < n; i++) {
    if (deg[i] % 3 == 2 && !vis[i]) {
      topo.clear(), comp.clear();
      dfs(i);
      if (ok) return;
      tree.push_back(comp);
    }
  }
  ans.clear();
  if (tree.size() < 2) {
    print();
    return;
  }
  if (ok) return;
  for (int i = 0; i < n; i++) {
    if (deg[i] % 3 == 1 && !vis[i]) root = i;
  }
  vector<int> l[2];
  for (int j = 0; j < 2; j++) {
    for (int i = 0; i < tree[j].size(); i++) {
      if (binary_search(adj[root].begin(), adj[root].end(), tree[j][i]))
        l[j].push_back(tree[j][i]);
    }
  }
  if (max(tree.size(), max(l[0].size(), l[1].size())) == 2) {
    ans.clear();
    print();
    return;
  }
  if (ok) return;
  ans.push_back(root);
  fill(par, par + n, 0);
  fill(dist, dist + n, inf);
  lca(l[0]), lca(l[1]);
  print();
  return;
}
int main() {
  int tc;
  cin >> tc;
  while (tc--) solve();
}
